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>