Annotation of libaitcfg/src/pwd.c, revision 1.2.4.1
1.2 misho 1: /*************************************************************************
2: * (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
3: * by Michael Pounov <misho@openbsd-bg.org>
4: *
5: * $Author: misho $
1.2.4.1 ! misho 6: * $Id: pwd.c,v 1.2 2012/09/19 15:22:32 misho Exp $
1.2 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.2.4.1 ! misho 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
1.2 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
46: #include "global.h"
47:
48:
49: #pragma GCC visibility push(hidden)
50:
51: inline int
52: pwd_tree_cmp(struct tagUser *a, struct tagUser *b)
53: {
54: assert(a && b);
55:
56: return strcmp(AIT_GET_STR(&a->usr_name), AIT_GET_STR(&b->usr_name));
57: }
58:
59: RB_GENERATE(tagPWD, tagUser, usr_node, pwd_tree_cmp);
60:
61: #pragma GCC visibility pop
62:
63: static inline void
64: _invertQueue(pwd_root_t * __restrict pwd)
65: {
66: struct tagUser *item, *next, *prev = NULL;
67:
68: SLIST_FOREACH_SAFE(item, pwd, usr_next, next) {
69: item->usr_next.sle_next = prev;
70: prev = item;
71: }
72: pwd->slh_first = prev;
73: }
74:
75:
76: /*
77: * cfgReadPasswd() - Read file and add new item at password root
78: *
79: * @f = File resource
80: * @pwd = Password root
81: * return: -1 error or 0 ok
82: */
83: int
84: cfgReadPasswd(FILE *f, pwd_root_t * __restrict pwd)
85: {
86: char line[BUFSIZ], *pos, *items[PWD_MAX_FIELDS];
87: struct tagUser *u;
88: register int i;
89:
90: if (!f || !pwd) {
91: cfg_SetErr(EINVAL, "Invalid parameter(s)");
92: return -1;
93: }
94:
95: while (!feof(f)) {
96: memset(line, 0, sizeof line);
97: fgets(line, sizeof line - 1, f);
98: if (!(pos = strpbrk(line, "\r\n"))) {
99: /* skip line, too long */
100: continue;
101: } else {
102: *pos = 0;
1.2.4.1 ! misho 103: str_Trim(line);
1.2 misho 104: }
105:
106: /* *NEW USER* alloc new element */
1.2.4.1 ! misho 107: u = e_malloc(sizeof(struct tagUser));
1.2 misho 108: if (!u) {
1.2.4.1 ! misho 109: cfg_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.2 misho 110: return -1;
111: } else {
112: memset(u, 0, sizeof(struct tagUser));
113: PWD_LOCK(pwd);
114: SLIST_INSERT_HEAD(pwd, u, usr_next);
115: PWD_UNLOCK(pwd);
116: }
117:
118: /* check for comment or empty line */
119: if (!*line || *line == '#' || *line == ';') {
120: AIT_SET_STR(&u->usr_realm, line);
121: continue;
122: }
123:
124: /* count & parse elements */
125: memset(items, 0, sizeof items);
126: for (i = 0, items[i] = pos = line; pos && i < (PWD_MAX_FIELDS - 2);)
127: if ((pos = strchr(pos, PWD_DELIM))) {
128: *pos++ = 0;
129: items[++i] = pos;
130: }
131: u->usr_fields = i;
132: AIT_SET_U32(&u->usr_uid, 0);
133: AIT_SET_U32(&u->usr_gid, 0);
134:
135: /* parse elements */
136: for (i = 0; i < (u->usr_fields + 1); i++) {
137: switch (i) {
138: case 0:
139: AIT_SET_STR(&u->usr_name, items[i]);
140: break;
141: case 1:
142: AIT_SET_STR(&u->usr_pass, items[i]);
143: break;
144: case 2:
145: AIT_SET_U32(&u->usr_uid, strtol(items[i], NULL, 10));
146: break;
147: case 3:
148: AIT_SET_U32(&u->usr_gid, strtol(items[i], NULL, 10));
149: break;
150: case 4:
151: AIT_SET_STR(&u->usr_class, items[i]);
152: break;
153: case 5:
154: AIT_SET_U32(&u->usr_change, strtol(items[i], NULL, 10));
155: break;
156: case 6:
157: AIT_SET_U32(&u->usr_expire, strtol(items[i], NULL, 10));
158: break;
159: case 7:
160: AIT_SET_STR(&u->usr_realm, items[i]);
161: break;
162: case 8:
163: AIT_SET_STR(&u->usr_home, items[i]);
164: break;
165: case 9:
166: AIT_SET_STR(&u->usr_shell, items[i]);
167: break;
168: }
169: }
170:
171: /* add to tree */
172: AIT_KEY(&u->usr_name) = crcFletcher16(AIT_GET_LIKE(&u->usr_name, u_short*),
1.2.4.1 ! misho 173: E_ALIGN(AIT_LEN(&u->usr_name) - 1, 2) / 2);
1.2 misho 174:
175: PWD_LOCK(pwd);
176: RB_INSERT(tagPWD, pwd, u);
177: PWD_UNLOCK(pwd);
178: }
179:
180: return 0;
181: }
182:
183: /*
184: * cfgWritePasswd() - Write passwords from memory
185: *
186: * @f = File handle
187: * @pwd = Password root
188: * return: -1 error or 0 ok
189: */
190: int
191: cfgWritePasswd(FILE *f, pwd_root_t * __restrict pwd)
192: {
193: struct tagUser *u;
194: char line[BUFSIZ];
195: int len = 0;
196: register int i;
197:
198: if (!f || !pwd) {
199: cfg_SetErr(EINVAL, "Invalid parameter(s)");
200: return -1;
201: }
202:
203: PWD_LOCK(pwd);
204: _invertQueue(pwd);
205: SLIST_FOREACH(u, pwd, usr_next) {
206: /* build line */
207: memset(line, 0, sizeof line);
208: /* comment or other senseless line */
209: if (AIT_ISEMPTY(&u->usr_name))
210: strlcpy(line, AIT_GET_STRZ(&u->usr_realm), sizeof line);
211: else {
212: for (i = 0; i < u->usr_fields + 1; i++) {
213: switch (i) {
214: case 0:
215: len = strlcpy(line, AIT_GET_STR(&u->usr_name), sizeof line);
216: break;
217: case 1:
218: len += snprintf(line + len, sizeof line, "%c%s", PWD_DELIM,
219: AIT_GET_STRZ(&u->usr_pass));
220: break;
221: case 2:
222: len += snprintf(line + len, sizeof line, "%c%u", PWD_DELIM,
223: AIT_GET_U32(&u->usr_uid));
224: break;
225: case 3:
226: len += snprintf(line + len, sizeof line, "%c%u", PWD_DELIM,
227: AIT_GET_U32(&u->usr_gid));
228: break;
229: case 4:
230: len += snprintf(line + len, sizeof line, "%c%s", PWD_DELIM,
231: AIT_GET_STRZ(&u->usr_class));
232: break;
233: case 5:
234: len += snprintf(line + len, sizeof line, "%c%u", PWD_DELIM,
235: AIT_GET_U32(&u->usr_change));
236: break;
237: case 6:
238: len += snprintf(line + len, sizeof line, "%c%u", PWD_DELIM,
239: AIT_GET_U32(&u->usr_expire));
240: break;
241: case 7:
242: len += snprintf(line + len, sizeof line, "%c%s", PWD_DELIM,
243: AIT_GET_STRZ(&u->usr_realm));
244: break;
245: case 8:
246: len += snprintf(line + len, sizeof line, "%c%s", PWD_DELIM,
247: AIT_GET_STRZ(&u->usr_home));
248: break;
249: case 9:
250: len += snprintf(line + len, sizeof line, "%c%s", PWD_DELIM,
251: AIT_GET_STRZ(&u->usr_shell));
252: break;
253: }
254: }
255: }
256:
257: /* write */
258: if (!cfg_Write(f, "%s\n", line)) {
259: LOGERR;
260: _invertQueue(pwd);
261: PWD_UNLOCK(pwd);
262: return -1;
263: }
264: }
265: _invertQueue(pwd);
266: PWD_UNLOCK(pwd);
267:
268: return 0;
269: }
270:
271: /*
272: * cfgConcatPasswd() - Concat two password roots into one
273: *
274: * @pwd = Password root
275: * @add_pwd = Concated password root will be destroy after merge
276: * return: -1 error or 0 ok
277: */
278: int
279: cfgConcatPasswd(pwd_root_t * __restrict pwd, pwd_root_t * __restrict add_pwd)
280: {
281: struct tagUser *item;
282:
283: if (!pwd || !add_pwd)
284: return -1;
285:
286: PWD_LOCK(add_pwd);
287: PWD_LOCK(pwd);
288:
289: /* concat items at the end */
290: for (item = SLIST_FIRST(pwd); SLIST_NEXT(item, usr_next); item = SLIST_NEXT(item, usr_next));
291: SLIST_NEXT(item, usr_next) = SLIST_FIRST(add_pwd);
292:
293: /* concat red-black trees */
294: SLIST_FOREACH(item, add_pwd, usr_next)
295: RB_INSERT(tagPWD, pwd, item);
296:
297: PWD_UNLOCK(pwd);
298:
299: add_pwd->slh_first = NULL;
300: add_pwd->rbh_root = NULL;
301: PWD_UNLOCK(add_pwd);
302: pthread_mutex_destroy(&add_pwd->pwd_mtx);
303: return 0;
304: }
305:
306: /*
307: * cfgAuthPasswd() - Authenticate user against passwords db
308: *
309: * @pwd = Password root
310: * @csName = Username
311: * @csPass = Password
312: * return: =NULL deny or !=NULL allow
313: */
314: const struct tagUser *
315: cfgAuthPasswd(pwd_root_t * __restrict pwd, const char *csName, const char *csPass)
316: {
317: const struct tagUser *u;
318:
319: if (!pwd || !csName)
320: return NULL;
321:
322: u = cfg_getPasswd(pwd, PWD_CRIT_NAME, csName);
323: if (u) {
324: if (!csPass) {
325: if (!AIT_ADDR(&u->usr_pass))
326: return u; /* allow */
327: } else {
328: if (AIT_ADDR(&u->usr_pass) &&
329: !strcmp(AIT_GET_STR(&u->usr_pass), csPass))
330: return u; /* allow */
331: }
332: }
333:
334: return NULL; /* deny */
335: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>