Annotation of libaitcfg/src/pwd.c, revision 1.4

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.4     ! misho       6: * $Id: pwd.c,v 1.3.4.1 2014/01/29 23:46:35 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.4     ! misho      15: Copyright 2004 - 2014
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.3       misho     103:                        str_Trim(line);
1.2       misho     104:                }
                    105: 
                    106:                /* *NEW USER* alloc new element */
1.3       misho     107:                u = e_malloc(sizeof(struct tagUser));
1.2       misho     108:                if (!u) {
1.3       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.3       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>