[BACK]Return to auth-bozo.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / libexec / httpd

Annotation of src/libexec/httpd/auth-bozo.c, Revision 1.4.16.1

1.4.16.1! msaitoh     1: /*     $NetBSD: auth-bozo.c,v 1.13 2014/07/08 14:01:21 mrg Exp $       */
1.3       tls         2:
1.4.16.1! msaitoh     3: /*     $eterna: auth-bozo.c,v 1.17 2011/11/18 09:21:15 mrg Exp $       */
1.1       tls         4:
                      5: /*
1.4.16.1! msaitoh     6:  * Copyright (c) 1997-2014 Matthew R. Green
1.1       tls         7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer and
                     16:  *    dedication in the documentation and/or other materials provided
                     17:  *    with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     20:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     21:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     22:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     23:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     24:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     25:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
                     26:  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     27:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     29:  * SUCH DAMAGE.
                     30:  *
                     31:  */
                     32:
                     33: /* this code implements "http basic authorisation" for bozohttpd */
                     34:
                     35: #ifdef DO_HTPASSWD
                     36:
                     37: #include <sys/param.h>
                     38:
                     39: #include <string.h>
1.4.16.1! msaitoh    40: #include <stdlib.h>
1.1       tls        41: #include <unistd.h>
                     42:
                     43: #include "bozohttpd.h"
                     44:
                     45: #ifndef AUTH_FILE
                     46: #define AUTH_FILE              ".htpasswd"
                     47: #endif
                     48:
                     49: static ssize_t base64_decode(const unsigned char *, size_t,
                     50:                            unsigned char *, size_t);
                     51:
                     52: /*
                     53:  * Check if HTTP authentication is required
                     54:  */
1.4.16.1! msaitoh    55: int
        !            56: bozo_auth_check(bozo_httpreq_t *request, const char *file)
1.1       tls        57: {
1.4.16.1! msaitoh    58:        bozohttpd_t *httpd = request->hr_httpd;
1.1       tls        59:        struct stat sb;
                     60:        char dir[MAXPATHLEN], authfile[MAXPATHLEN], *basename;
                     61:        char user[BUFSIZ], *pass;
                     62:        FILE *fp;
                     63:        int len;
                     64:
                     65:                        /* get dir=dirname(file) */
                     66:        snprintf(dir, sizeof(dir), "%s", file);
                     67:        if ((basename = strrchr(dir, '/')) == NULL)
                     68:                strcpy(dir, ".");
                     69:        else {
                     70:                *basename++ = '\0';
                     71:                        /* ensure basename(file) != AUTH_FILE */
1.4.16.1! msaitoh    72:                if (bozo_check_special_files(request, basename))
        !            73:                        return 1;
1.1       tls        74:        }
1.4.16.1! msaitoh    75:        request->hr_authrealm = bozostrdup(httpd, dir);
1.1       tls        76:
1.4.16.1! msaitoh    77:        if ((size_t)snprintf(authfile, sizeof(authfile), "%s/%s", dir, AUTH_FILE) >=
        !            78:          sizeof(authfile)) {
        !            79:                return bozo_http_error(httpd, 404, request,
        !            80:                        "authfile path too long");
        !            81:        }
1.1       tls        82:        if (stat(authfile, &sb) < 0) {
1.4.16.1! msaitoh    83:                debug((httpd, DEBUG_NORMAL,
        !            84:                    "bozo_auth_check realm `%s' dir `%s' authfile `%s' missing",
1.1       tls        85:                    dir, file, authfile));
1.4.16.1! msaitoh    86:                return 0;
1.1       tls        87:        }
                     88:        if ((fp = fopen(authfile, "r")) == NULL)
1.4.16.1! msaitoh    89:                return bozo_http_error(httpd, 403, request,
        !            90:                        "no permission to open authfile");
        !            91:        debug((httpd, DEBUG_NORMAL,
        !            92:            "bozo_auth_check realm `%s' dir `%s' authfile `%s' open",
1.1       tls        93:            dir, file, authfile));
                     94:        if (request->hr_authuser && request->hr_authpass) {
                     95:                while (fgets(user, sizeof(user), fp) != NULL) {
                     96:                        len = strlen(user);
                     97:                        if (len > 0 && user[len-1] == '\n')
                     98:                                user[--len] = '\0';
                     99:                        if ((pass = strchr(user, ':')) == NULL)
                    100:                                continue;
                    101:                        *pass++ = '\0';
1.4.16.1! msaitoh   102:                        debug((httpd, DEBUG_NORMAL,
        !           103:                            "bozo_auth_check authfile `%s':`%s' "
        !           104:                                "client `%s':`%s'",
1.1       tls       105:                            user, pass, request->hr_authuser,
                    106:                            request->hr_authpass));
                    107:                        if (strcmp(request->hr_authuser, user) != 0)
                    108:                                continue;
1.4.16.1! msaitoh   109:                        if (strcmp(crypt(request->hr_authpass, pass),
        !           110:                                        pass) != 0)
1.1       tls       111:                                break;
                    112:                        fclose(fp);
1.4.16.1! msaitoh   113:                        return 0;
1.1       tls       114:                }
                    115:        }
                    116:        fclose(fp);
1.4.16.1! msaitoh   117:        return bozo_http_error(httpd, 401, request, "bad auth");
        !           118: }
        !           119:
        !           120: void
        !           121: bozo_auth_cleanup(bozo_httpreq_t *request)
        !           122: {
        !           123:
        !           124:        if (request == NULL)
        !           125:                return;
        !           126:        free(request->hr_authuser);
        !           127:        free(request->hr_authpass);
        !           128:        free(request->hr_authrealm);
1.1       tls       129: }
                    130:
                    131: int
1.4.16.1! msaitoh   132: bozo_auth_check_headers(bozo_httpreq_t *request, char *val, char *str, ssize_t len)
1.1       tls       133: {
1.4.16.1! msaitoh   134:        bozohttpd_t *httpd = request->hr_httpd;
        !           135:
1.1       tls       136:        if (strcasecmp(val, "authorization") == 0 &&
                    137:            strncasecmp(str, "Basic ", 6) == 0) {
                    138:                char    authbuf[BUFSIZ];
1.2       reed      139:                char    *pass = NULL;
1.1       tls       140:                ssize_t alen;
                    141:
1.4.16.1! msaitoh   142:                alen = base64_decode((unsigned char *)str + 6,
        !           143:                                        (size_t)(len - 6),
        !           144:                                        (unsigned char *)authbuf,
        !           145:                                        sizeof(authbuf) - 1);
1.1       tls       146:                if (alen != -1)
                    147:                        authbuf[alen] = '\0';
                    148:                if (alen == -1 ||
                    149:                    (pass = strchr(authbuf, ':')) == NULL)
1.4.16.1! msaitoh   150:                        return bozo_http_error(httpd, 400, request,
1.1       tls       151:                            "bad authorization field");
                    152:                *pass++ = '\0';
1.4.16.1! msaitoh   153:                request->hr_authuser = bozostrdup(httpd, authbuf);
        !           154:                request->hr_authpass = bozostrdup(httpd, pass);
        !           155:                debug((httpd, DEBUG_FAT,
1.1       tls       156:                    "decoded authorization `%s' as `%s':`%s'",
                    157:                    str, request->hr_authuser, request->hr_authpass));
                    158:                        /* don't store in request->headers */
                    159:                return 1;
                    160:        }
                    161:        return 0;
                    162: }
                    163:
1.4.16.1! msaitoh   164: int
        !           165: bozo_auth_check_special_files(bozo_httpreq_t *request,
        !           166:                                const char *name)
1.1       tls       167: {
1.4.16.1! msaitoh   168:        bozohttpd_t *httpd = request->hr_httpd;
        !           169:
1.1       tls       170:        if (strcmp(name, AUTH_FILE) == 0)
1.4.16.1! msaitoh   171:                return bozo_http_error(httpd, 403, request,
        !           172:                                "no permission to open authfile");
        !           173:        return 0;
1.1       tls       174: }
                    175:
                    176: void
1.4.16.1! msaitoh   177: bozo_auth_check_401(bozo_httpreq_t *request, int code)
1.1       tls       178: {
1.4.16.1! msaitoh   179:        bozohttpd_t *httpd = request->hr_httpd;
        !           180:
1.1       tls       181:        if (code == 401)
1.4.16.1! msaitoh   182:                bozo_printf(httpd,
        !           183:                        "WWW-Authenticate: Basic realm=\"%s\"\r\n",
        !           184:                        (request && request->hr_authrealm) ?
        !           185:                                request->hr_authrealm : "default realm");
1.1       tls       186: }
                    187:
                    188: #ifndef NO_CGIBIN_SUPPORT
                    189: void
1.4.16.1! msaitoh   190: bozo_auth_cgi_setenv(bozo_httpreq_t *request,
        !           191:                        char ***curenvpp)
1.1       tls       192: {
1.4.16.1! msaitoh   193:        bozohttpd_t *httpd = request->hr_httpd;
        !           194:
1.1       tls       195:        if (request->hr_authuser && *request->hr_authuser) {
1.4.16.1! msaitoh   196:                bozo_setenv(httpd, "AUTH_TYPE", "Basic", (*curenvpp)++);
        !           197:                bozo_setenv(httpd, "REMOTE_USER", request->hr_authuser,
        !           198:                                (*curenvpp)++);
1.1       tls       199:        }
                    200: }
                    201:
                    202: int
1.4.16.1! msaitoh   203: bozo_auth_cgi_count(bozo_httpreq_t *request)
1.1       tls       204: {
                    205:        return (request->hr_authuser && *request->hr_authuser) ? 2 : 0;
                    206: }
                    207: #endif /* NO_CGIBIN_SUPPORT */
                    208:
                    209: /*
                    210:  * Decode len bytes starting at in using base64 encoding into out.
                    211:  * Result is *not* NUL terminated.
                    212:  * Written by Luke Mewburn <lukem@NetBSD.org>
                    213:  */
                    214: const unsigned char decodetable[] = {
                    215:        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
                    216:        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
                    217:        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
                    218:         52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255, 255,   0, 255, 255,
                    219:        255,   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
                    220:         15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,
                    221:        255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,
                    222:         41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51, 255, 255, 255, 255, 255,
                    223: };
                    224:
                    225: static ssize_t
                    226: base64_decode(const unsigned char *in, size_t ilen, unsigned char *out,
                    227:              size_t olen)
                    228: {
                    229:        unsigned char *cp;
                    230:        size_t   i;
                    231:
                    232:        cp = out;
                    233:        for (i = 0; i < ilen; i += 4) {
                    234:                if (cp + 3 > out + olen)
                    235:                        return (-1);
                    236: #define IN_CHECK(x) \
                    237:                if ((x) > sizeof(decodetable) || decodetable[(x)] == 255) \
                    238:                            return(-1)
                    239:
                    240:                IN_CHECK(in[i + 0]);
1.4.16.1! msaitoh   241:                /*LINTED*/
1.1       tls       242:                *(cp++) = decodetable[in[i + 0]] << 2
                    243:                        | decodetable[in[i + 1]] >> 4;
                    244:                IN_CHECK(in[i + 1]);
1.4.16.1! msaitoh   245:                /*LINTED*/
1.1       tls       246:                *(cp++) = decodetable[in[i + 1]] << 4
                    247:                        | decodetable[in[i + 2]] >> 2;
                    248:                IN_CHECK(in[i + 2]);
                    249:                *(cp++) = decodetable[in[i + 2]] << 6
                    250:                        | decodetable[in[i + 3]];
                    251: #undef IN_CHECK
                    252:        }
                    253:        while (in[i - 1] == '=')
                    254:                cp--,i--;
                    255:        return (cp - out);
                    256: }
                    257: #endif /* DO_HTPASSWD */

CVSweb <webmaster@jp.NetBSD.org>