blob: 203b5aaf7d0b1a83bc83ead898ebb926d02635f4 [file] [log] [blame]
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +01001/*
2 * User authentication & authorization
3 *
4 * Copyright 2010 Krzysztof Piotr Oledzki <ole@ans.pl>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 */
12
Willy Tarreau890a33e2010-03-04 19:10:14 +010013#ifdef CONFIG_HAP_CRYPT
14/* This is to have crypt() defined on Linux */
15#define _GNU_SOURCE
16
17#ifdef NEED_CRYPT_H
18/* some platforms such as Solaris need this */
19#include <crypt.h>
20#endif
21#endif /* CONFIG_HAP_CRYPT */
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010022
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27
28#include <common/config.h>
29
30#include <proto/acl.h>
31#include <proto/log.h>
32
33#include <types/auth.h>
Thierry FOURNIERa65b3432013-11-28 18:22:00 +010034#include <types/pattern.h>
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010035
36struct userlist *userlist = NULL; /* list of all existing userlists */
37
38/* find targets for selected gropus. The function returns pointer to
39 * the userlist struct ot NULL if name is NULL/empty or unresolvable.
40 */
41
42struct userlist *
43auth_find_userlist(char *name)
44{
45 struct userlist *l;
46
47 if (!name || !*name)
48 return NULL;
49
50 for (l = userlist; l; l = l->next)
51 if (!strcmp(l->name, name))
52 return l;
53
54 return NULL;
55}
56
57/* find group_mask for selected gropus. The function returns 1 if OK or nothing to do,
58 * 0 if case of unresolved groupname.
59 * WARING: the function destroys the list (strtok), so it can only be used once.
60 */
61
62unsigned int
63auth_resolve_groups(struct userlist *l, char *groups)
64{
65
66 char *group = NULL;
67 unsigned int g, group_mask = 0;
68
69 if (!groups || !*groups)
70 return 0;
71
72 while ((group = strtok(group?NULL:groups," "))) {
73 for (g = 0; g < l->grpcnt; g++)
74 if (!strcmp(l->groups[g], group))
75 break;
76
77 if (g == l->grpcnt) {
78 Alert("No such group '%s' in userlist '%s'.\n",
79 group, l->name);
80 return 0;
81 }
82
83 group_mask |= (1 << g);
84 }
85
86 return group_mask;
87}
88
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +010089void
90userlist_free(struct userlist *ul)
91{
92 struct userlist *tul;
93 struct auth_users *au, *tau;
94 int i;
95
96 while (ul) {
97 au = ul->users;
98 while (au) {
99 tau = au;
100 au = au->next;
101 free(tau->user);
102 free(tau->pass);
103 free(tau);
104 }
105
106 tul = ul;
107 ul = ul->next;
108
109 for (i = 0; i < tul->grpcnt; i++)
110 free(tul->groups[i]);
111
112 free(tul->name);
113 free(tul);
114 };
115}
116
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100117/*
118 * Authenticate and authorize user; return 1 if OK, 0 if case of error.
119 */
120int
121check_user(struct userlist *ul, unsigned int group_mask, const char *user, const char *pass)
122{
123
124 struct auth_users *u;
125 const char *ep;
126
127#ifdef DEBUG_AUTH
128 fprintf(stderr, "req: userlist=%s, user=%s, pass=%s, group_mask=%u\n",
129 ul->name, user, pass, group_mask);
130#endif
131
132 for (u = ul->users; u; u = u->next)
133 if (!strcmp(user, u->user))
134 break;
135
136 if (!u)
137 return 0;
138
139#ifdef DEBUG_AUTH
140 fprintf(stderr, "cfg: user=%s, pass=%s, group_mask=%u, flags=%X",
Willy Tarreaub9509592012-05-10 23:25:35 +0200141 u->user, u->pass, u->u.group_mask, u->flags);
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100142#endif
143
144 /*
145 * if user matches but group does not,
146 * it makes no sens to check passwords
147 */
Willy Tarreaub4c06b72010-02-02 11:28:20 +0100148 if (group_mask && !(group_mask & u->u.group_mask))
Krzysztof Piotr Oledzki96105042010-01-29 17:50:44 +0100149 return 0;
150
151 if (!(u->flags & AU_O_INSECURE)) {
152#ifdef CONFIG_HAP_CRYPT
153 ep = crypt(pass, u->pass);
154#else
155 return 0;
156#endif
157 } else
158 ep = pass;
159
160#ifdef DEBUG_AUTH
161 fprintf(stderr, ", crypt=%s\n", ep);
162#endif
163
164 if (!strcmp(ep, u->pass))
165 return 1;
166 else
167 return 0;
168}
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100169
Willy Tarreau0cba6072013-11-28 22:21:02 +0100170enum pat_match_res
Thierry FOURNIERa65b3432013-11-28 18:22:00 +0100171pat_match_auth(struct sample *smp, struct pattern *pattern)
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100172{
173
Willy Tarreau37406352012-04-23 16:16:37 +0200174 struct userlist *ul = smp->ctx.a[0];
175 char *user = smp->ctx.a[1];
176 char *pass = smp->ctx.a[2];
Willy Tarreau8f7406e2012-04-20 18:16:26 +0200177 unsigned int group_mask = pattern->val.group_mask;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100178
179 if (check_user(ul, group_mask, user, pass))
Thierry FOURNIERa65b3432013-11-28 18:22:00 +0100180 return PAT_MATCH;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100181 else
Thierry FOURNIERa65b3432013-11-28 18:22:00 +0100182 return PAT_NOMATCH;
Krzysztof Piotr Oledzkif9423ae2010-01-29 19:26:18 +0100183}