[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

1.4     ! mrg         1: /*     $NetBSD: auth-bozo.c,v 1.3 2007/10/17 18:47:59 tls Exp $        */
1.3       tls         2:
1.4     ! mrg         3: /*     $eterna: auth-bozo.c,v 1.8 2008/03/03 03:36:11 mrg Exp $        */
1.1       tls         4:
                      5: /*
1.4     ! mrg         6:  * Copyright (c) 1997-2008 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:  * 3. The name of the author may not be used to endorse or promote products
                     19:  *    derived from this software without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
                     26:  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
                     27:  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
                     28:  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
                     29:  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     31:  * SUCH DAMAGE.
                     32:  *
                     33:  */
                     34:
                     35: /* this code implements "http basic authorisation" for bozohttpd */
                     36:
                     37: #ifdef DO_HTPASSWD
                     38:
                     39: #include <sys/param.h>
                     40:
                     41: #include <string.h>
                     42: #include <unistd.h>
                     43:
                     44: #include "bozohttpd.h"
                     45:
                     46: #ifndef AUTH_FILE
                     47: #define AUTH_FILE              ".htpasswd"
                     48: #endif
                     49:
                     50: static ssize_t base64_decode(const unsigned char *, size_t,
                     51:                            unsigned char *, size_t);
                     52:
                     53: /*
                     54:  * Check if HTTP authentication is required
                     55:  */
                     56: void
                     57: auth_check(http_req *request, const char *file)
                     58: {
                     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 */
                     72:                check_special_files(request, basename);
                     73:        }
                     74:        request->hr_authrealm = dir;
                     75:
                     76:        snprintf(authfile, sizeof(authfile), "%s/%s", dir, AUTH_FILE);
                     77:        if (stat(authfile, &sb) < 0) {
                     78:                debug((DEBUG_NORMAL,
                     79:                    "auth_check realm `%s' dir `%s' authfile `%s' missing",
                     80:                    dir, file, authfile));
                     81:                return;
                     82:        }
                     83:        if ((fp = fopen(authfile, "r")) == NULL)
                     84:                http_error(403, request, "no permission to open authfile");
                     85:        debug((DEBUG_NORMAL,
                     86:            "auth_check realm `%s' dir `%s' authfile `%s' open",
                     87:            dir, file, authfile));
                     88:        if (request->hr_authuser && request->hr_authpass) {
                     89:                while (fgets(user, sizeof(user), fp) != NULL) {
                     90:                        len = strlen(user);
                     91:                        if (len > 0 && user[len-1] == '\n')
                     92:                                user[--len] = '\0';
                     93:                        if ((pass = strchr(user, ':')) == NULL)
                     94:                                continue;
                     95:                        *pass++ = '\0';
                     96:                        debug((DEBUG_NORMAL,
                     97:                            "auth_check authfile `%s':`%s' client `%s':`%s'",
                     98:                            user, pass, request->hr_authuser,
                     99:                            request->hr_authpass));
                    100:                        if (strcmp(request->hr_authuser, user) != 0)
                    101:                                continue;
                    102:                        if (strcmp(crypt(request->hr_authpass, pass), pass))
                    103:                                break;
                    104:                        fclose(fp);
                    105:                        return;
                    106:                }
                    107:        }
                    108:        fclose(fp);
                    109:        http_error(401, request, "bad auth");
                    110: }
                    111:
                    112: int
                    113: auth_check_headers(http_req *request, char *val, char *str, ssize_t len)
                    114: {
                    115:        if (strcasecmp(val, "authorization") == 0 &&
                    116:            strncasecmp(str, "Basic ", 6) == 0) {
                    117:                char    authbuf[BUFSIZ];
1.2       reed      118:                char    *pass = NULL;
1.1       tls       119:                ssize_t alen;
                    120:
1.2       reed      121:                alen = base64_decode((unsigned char *)str + 6, len - 6,
                    122:                    (unsigned char *)authbuf, sizeof(authbuf) - 1);
1.1       tls       123:                if (alen != -1)
                    124:                        authbuf[alen] = '\0';
                    125:                if (alen == -1 ||
                    126:                    (pass = strchr(authbuf, ':')) == NULL)
                    127:                        http_error(400, request,
                    128:                            "bad authorization field");
                    129:                *pass++ = '\0';
                    130:                request->hr_authuser = bozostrdup(authbuf);
                    131:                request->hr_authpass = bozostrdup(pass);
                    132:                debug((DEBUG_FAT,
                    133:                    "decoded authorization `%s' as `%s':`%s'",
                    134:                    str, request->hr_authuser, request->hr_authpass));
                    135:                        /* don't store in request->headers */
                    136:                return 1;
                    137:        }
                    138:        return 0;
                    139: }
                    140:
                    141: void
                    142: auth_check_special_files(http_req *request, const char *name)
                    143: {
                    144:        if (strcmp(name, AUTH_FILE) == 0)
                    145:                http_error(403, request, "no permission to open authfile");
                    146: }
                    147:
                    148: void
                    149: auth_check_401(http_req *request, int code)
                    150: {
                    151:        if (code == 401)
                    152:                bozoprintf("WWW-Authenticate: Basic realm=\"%s\"\r\n",
                    153:                    request && request->hr_authrealm ? request->hr_authrealm :
                    154:                    "default realm");
                    155: }
                    156:
                    157: #ifndef NO_CGIBIN_SUPPORT
                    158: void
                    159: auth_cgi_setenv(http_req *request, char ***curenvpp)
                    160: {
                    161:        if (request->hr_authuser && *request->hr_authuser) {
                    162:                spsetenv("AUTH_TYPE", "Basic", (*curenvpp)++);
                    163:                spsetenv("REMOTEUSER", request->hr_authuser, (*curenvpp)++);
                    164:        }
                    165: }
                    166:
                    167: int
                    168: auth_cgi_count(http_req *request)
                    169: {
                    170:        return (request->hr_authuser && *request->hr_authuser) ? 2 : 0;
                    171: }
                    172: #endif /* NO_CGIBIN_SUPPORT */
                    173:
                    174: /*
                    175:  * Decode len bytes starting at in using base64 encoding into out.
                    176:  * Result is *not* NUL terminated.
                    177:  * Written by Luke Mewburn <lukem@NetBSD.org>
                    178:  */
                    179: const unsigned char decodetable[] = {
                    180:        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
                    181:        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
                    182:        255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,  62, 255, 255, 255,  63,
                    183:         52,  53,  54,  55,  56,  57,  58,  59,  60,  61, 255, 255, 255,   0, 255, 255,
                    184:        255,   0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
                    185:         15,  16,  17,  18,  19,  20,  21,  22,  23,  24,  25, 255, 255, 255, 255, 255,
                    186:        255,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,  40,
                    187:         41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51, 255, 255, 255, 255, 255,
                    188: };
                    189:
                    190: static ssize_t
                    191: base64_decode(const unsigned char *in, size_t ilen, unsigned char *out,
                    192:              size_t olen)
                    193: {
                    194:        unsigned char *cp;
                    195:        size_t   i;
                    196:
                    197:        cp = out;
                    198:        for (i = 0; i < ilen; i += 4) {
                    199:                if (cp + 3 > out + olen)
                    200:                        return (-1);
                    201: #define IN_CHECK(x) \
                    202:                if ((x) > sizeof(decodetable) || decodetable[(x)] == 255) \
                    203:                            return(-1)
                    204:
                    205:                IN_CHECK(in[i + 0]);
                    206:                *(cp++) = decodetable[in[i + 0]] << 2
                    207:                        | decodetable[in[i + 1]] >> 4;
                    208:                IN_CHECK(in[i + 1]);
                    209:                *(cp++) = decodetable[in[i + 1]] << 4
                    210:                        | decodetable[in[i + 2]] >> 2;
                    211:                IN_CHECK(in[i + 2]);
                    212:                *(cp++) = decodetable[in[i + 2]] << 6
                    213:                        | decodetable[in[i + 3]];
                    214: #undef IN_CHECK
                    215:        }
                    216:        while (in[i - 1] == '=')
                    217:                cp--,i--;
                    218:        return (cp - out);
                    219: }
                    220: #endif /* DO_HTPASSWD */

CVSweb <webmaster@jp.NetBSD.org>