Annotation of libaitcfg/src/pwd.c, revision 1.2
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 $
! 6: * $Id: pwd.c,v 1.1.2.1 2012/09/19 13:46:46 misho Exp $
! 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:
! 15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
! 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: #include "aitpwd.h"
! 48:
! 49:
! 50: #pragma GCC visibility push(hidden)
! 51:
! 52: inline int
! 53: pwd_tree_cmp(struct tagUser *a, struct tagUser *b)
! 54: {
! 55: assert(a && b);
! 56:
! 57: return strcmp(AIT_GET_STR(&a->usr_name), AIT_GET_STR(&b->usr_name));
! 58: }
! 59:
! 60: RB_GENERATE(tagPWD, tagUser, usr_node, pwd_tree_cmp);
! 61:
! 62: #pragma GCC visibility pop
! 63:
! 64: static inline void
! 65: _invertQueue(pwd_root_t * __restrict pwd)
! 66: {
! 67: struct tagUser *item, *next, *prev = NULL;
! 68:
! 69: SLIST_FOREACH_SAFE(item, pwd, usr_next, next) {
! 70: item->usr_next.sle_next = prev;
! 71: prev = item;
! 72: }
! 73: pwd->slh_first = prev;
! 74: }
! 75:
! 76:
! 77: /*
! 78: * cfgReadPasswd() - Read file and add new item at password root
! 79: *
! 80: * @f = File resource
! 81: * @pwd = Password root
! 82: * return: -1 error or 0 ok
! 83: */
! 84: int
! 85: cfgReadPasswd(FILE *f, pwd_root_t * __restrict pwd)
! 86: {
! 87: char line[BUFSIZ], *pos, *items[PWD_MAX_FIELDS];
! 88: struct tagUser *u;
! 89: register int i;
! 90:
! 91: if (!f || !pwd) {
! 92: cfg_SetErr(EINVAL, "Invalid parameter(s)");
! 93: return -1;
! 94: }
! 95:
! 96: while (!feof(f)) {
! 97: memset(line, 0, sizeof line);
! 98: fgets(line, sizeof line - 1, f);
! 99: if (!(pos = strpbrk(line, "\r\n"))) {
! 100: /* skip line, too long */
! 101: continue;
! 102: } else {
! 103: *pos = 0;
! 104: io_TrimStr(line);
! 105: }
! 106:
! 107: /* *NEW USER* alloc new element */
! 108: u = io_malloc(sizeof(struct tagUser));
! 109: if (!u) {
! 110: cfg_SetErr(io_GetErrno(), "%s", io_GetError());
! 111: return -1;
! 112: } else {
! 113: memset(u, 0, sizeof(struct tagUser));
! 114: PWD_LOCK(pwd);
! 115: SLIST_INSERT_HEAD(pwd, u, usr_next);
! 116: PWD_UNLOCK(pwd);
! 117: }
! 118:
! 119: /* check for comment or empty line */
! 120: if (!*line || *line == '#' || *line == ';') {
! 121: AIT_SET_STR(&u->usr_realm, line);
! 122: continue;
! 123: }
! 124:
! 125: /* count & parse elements */
! 126: memset(items, 0, sizeof items);
! 127: for (i = 0, items[i] = pos = line; pos && i < (PWD_MAX_FIELDS - 2);)
! 128: if ((pos = strchr(pos, PWD_DELIM))) {
! 129: *pos++ = 0;
! 130: items[++i] = pos;
! 131: }
! 132: u->usr_fields = i;
! 133: AIT_SET_U32(&u->usr_uid, 0);
! 134: AIT_SET_U32(&u->usr_gid, 0);
! 135:
! 136: /* parse elements */
! 137: for (i = 0; i < (u->usr_fields + 1); i++) {
! 138: switch (i) {
! 139: case 0:
! 140: AIT_SET_STR(&u->usr_name, items[i]);
! 141: break;
! 142: case 1:
! 143: AIT_SET_STR(&u->usr_pass, items[i]);
! 144: break;
! 145: case 2:
! 146: AIT_SET_U32(&u->usr_uid, strtol(items[i], NULL, 10));
! 147: break;
! 148: case 3:
! 149: AIT_SET_U32(&u->usr_gid, strtol(items[i], NULL, 10));
! 150: break;
! 151: case 4:
! 152: AIT_SET_STR(&u->usr_class, items[i]);
! 153: break;
! 154: case 5:
! 155: AIT_SET_U32(&u->usr_change, strtol(items[i], NULL, 10));
! 156: break;
! 157: case 6:
! 158: AIT_SET_U32(&u->usr_expire, strtol(items[i], NULL, 10));
! 159: break;
! 160: case 7:
! 161: AIT_SET_STR(&u->usr_realm, items[i]);
! 162: break;
! 163: case 8:
! 164: AIT_SET_STR(&u->usr_home, items[i]);
! 165: break;
! 166: case 9:
! 167: AIT_SET_STR(&u->usr_shell, items[i]);
! 168: break;
! 169: }
! 170: }
! 171:
! 172: /* add to tree */
! 173: AIT_KEY(&u->usr_name) = crcFletcher16(AIT_GET_LIKE(&u->usr_name, u_short*),
! 174: io_align(AIT_LEN(&u->usr_name) - 1, 2) / 2);
! 175:
! 176: PWD_LOCK(pwd);
! 177: RB_INSERT(tagPWD, pwd, u);
! 178: PWD_UNLOCK(pwd);
! 179: }
! 180:
! 181: return 0;
! 182: }
! 183:
! 184: /*
! 185: * cfgWritePasswd() - Write passwords from memory
! 186: *
! 187: * @f = File handle
! 188: * @pwd = Password root
! 189: * return: -1 error or 0 ok
! 190: */
! 191: int
! 192: cfgWritePasswd(FILE *f, pwd_root_t * __restrict pwd)
! 193: {
! 194: struct tagUser *u;
! 195: char line[BUFSIZ];
! 196: int len = 0;
! 197: register int i;
! 198:
! 199: if (!f || !pwd) {
! 200: cfg_SetErr(EINVAL, "Invalid parameter(s)");
! 201: return -1;
! 202: }
! 203:
! 204: PWD_LOCK(pwd);
! 205: _invertQueue(pwd);
! 206: SLIST_FOREACH(u, pwd, usr_next) {
! 207: /* build line */
! 208: memset(line, 0, sizeof line);
! 209: /* comment or other senseless line */
! 210: if (AIT_ISEMPTY(&u->usr_name))
! 211: strlcpy(line, AIT_GET_STRZ(&u->usr_realm), sizeof line);
! 212: else {
! 213: for (i = 0; i < u->usr_fields + 1; i++) {
! 214: switch (i) {
! 215: case 0:
! 216: len = strlcpy(line, AIT_GET_STR(&u->usr_name), sizeof line);
! 217: break;
! 218: case 1:
! 219: len += snprintf(line + len, sizeof line, "%c%s", PWD_DELIM,
! 220: AIT_GET_STRZ(&u->usr_pass));
! 221: break;
! 222: case 2:
! 223: len += snprintf(line + len, sizeof line, "%c%u", PWD_DELIM,
! 224: AIT_GET_U32(&u->usr_uid));
! 225: break;
! 226: case 3:
! 227: len += snprintf(line + len, sizeof line, "%c%u", PWD_DELIM,
! 228: AIT_GET_U32(&u->usr_gid));
! 229: break;
! 230: case 4:
! 231: len += snprintf(line + len, sizeof line, "%c%s", PWD_DELIM,
! 232: AIT_GET_STRZ(&u->usr_class));
! 233: break;
! 234: case 5:
! 235: len += snprintf(line + len, sizeof line, "%c%u", PWD_DELIM,
! 236: AIT_GET_U32(&u->usr_change));
! 237: break;
! 238: case 6:
! 239: len += snprintf(line + len, sizeof line, "%c%u", PWD_DELIM,
! 240: AIT_GET_U32(&u->usr_expire));
! 241: break;
! 242: case 7:
! 243: len += snprintf(line + len, sizeof line, "%c%s", PWD_DELIM,
! 244: AIT_GET_STRZ(&u->usr_realm));
! 245: break;
! 246: case 8:
! 247: len += snprintf(line + len, sizeof line, "%c%s", PWD_DELIM,
! 248: AIT_GET_STRZ(&u->usr_home));
! 249: break;
! 250: case 9:
! 251: len += snprintf(line + len, sizeof line, "%c%s", PWD_DELIM,
! 252: AIT_GET_STRZ(&u->usr_shell));
! 253: break;
! 254: }
! 255: }
! 256: }
! 257:
! 258: /* write */
! 259: if (!cfg_Write(f, "%s\n", line)) {
! 260: LOGERR;
! 261: _invertQueue(pwd);
! 262: PWD_UNLOCK(pwd);
! 263: return -1;
! 264: }
! 265: }
! 266: _invertQueue(pwd);
! 267: PWD_UNLOCK(pwd);
! 268:
! 269: return 0;
! 270: }
! 271:
! 272: /*
! 273: * cfgConcatPasswd() - Concat two password roots into one
! 274: *
! 275: * @pwd = Password root
! 276: * @add_pwd = Concated password root will be destroy after merge
! 277: * return: -1 error or 0 ok
! 278: */
! 279: int
! 280: cfgConcatPasswd(pwd_root_t * __restrict pwd, pwd_root_t * __restrict add_pwd)
! 281: {
! 282: struct tagUser *item;
! 283:
! 284: if (!pwd || !add_pwd)
! 285: return -1;
! 286:
! 287: PWD_LOCK(add_pwd);
! 288: PWD_LOCK(pwd);
! 289:
! 290: /* concat items at the end */
! 291: for (item = SLIST_FIRST(pwd); SLIST_NEXT(item, usr_next); item = SLIST_NEXT(item, usr_next));
! 292: SLIST_NEXT(item, usr_next) = SLIST_FIRST(add_pwd);
! 293:
! 294: /* concat red-black trees */
! 295: SLIST_FOREACH(item, add_pwd, usr_next)
! 296: RB_INSERT(tagPWD, pwd, item);
! 297:
! 298: PWD_UNLOCK(pwd);
! 299:
! 300: add_pwd->slh_first = NULL;
! 301: add_pwd->rbh_root = NULL;
! 302: PWD_UNLOCK(add_pwd);
! 303: pthread_mutex_destroy(&add_pwd->pwd_mtx);
! 304: return 0;
! 305: }
! 306:
! 307: /*
! 308: * cfgAuthPasswd() - Authenticate user against passwords db
! 309: *
! 310: * @pwd = Password root
! 311: * @csName = Username
! 312: * @csPass = Password
! 313: * return: =NULL deny or !=NULL allow
! 314: */
! 315: const struct tagUser *
! 316: cfgAuthPasswd(pwd_root_t * __restrict pwd, const char *csName, const char *csPass)
! 317: {
! 318: const struct tagUser *u;
! 319:
! 320: if (!pwd || !csName)
! 321: return NULL;
! 322:
! 323: u = cfg_getPasswd(pwd, PWD_CRIT_NAME, csName);
! 324: if (u) {
! 325: if (!csPass) {
! 326: if (!AIT_ADDR(&u->usr_pass))
! 327: return u; /* allow */
! 328: } else {
! 329: if (AIT_ADDR(&u->usr_pass) &&
! 330: !strcmp(AIT_GET_STR(&u->usr_pass), csPass))
! 331: return u; /* allow */
! 332: }
! 333: }
! 334:
! 335: return NULL; /* deny */
! 336: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>