Annotation of libaitcfg/src/pwd.c, revision 1.4.24.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.4.24.1! misho       6: * $Id: pwd.c,v 1.4 2014/01/29 23:48:34 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.24.1! misho      15: Copyright 2004 - 2022
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);
1.4.24.1! misho      97:                if (!fgets(line, sizeof(line) - 1, f))
        !            98:                        break;
1.2       misho      99:                if (!(pos = strpbrk(line, "\r\n"))) {
                    100:                        /* skip line, too long */
                    101:                        continue;
                    102:                } else {
                    103:                        *pos = 0;
1.3       misho     104:                        str_Trim(line);
1.2       misho     105:                }
                    106: 
                    107:                /* *NEW USER* alloc new element */
1.3       misho     108:                u = e_malloc(sizeof(struct tagUser));
1.2       misho     109:                if (!u) {
1.3       misho     110:                        cfg_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
1.2       misho     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*), 
1.3       misho     174:                                E_ALIGN(AIT_LEN(&u->usr_name) - 1, 2) / 2);
1.2       misho     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>