Annotation of embedaddon/lighttpd/src/mod_auth.c, revision 1.1
1.1 ! misho 1: #include "plugin.h"
! 2: #include "http_auth.h"
! 3: #include "log.h"
! 4: #include "response.h"
! 5:
! 6: #include <sys/types.h>
! 7: #include <sys/stat.h>
! 8:
! 9: #include <stdlib.h>
! 10: #include <string.h>
! 11: #include <errno.h>
! 12: #include <fcntl.h>
! 13: #include <unistd.h>
! 14:
! 15: handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s);
! 16:
! 17:
! 18: /**
! 19: * the basic and digest auth framework
! 20: *
! 21: * - config handling
! 22: * - protocol handling
! 23: *
! 24: * http_auth.c
! 25: * http_auth_digest.c
! 26: *
! 27: * do the real work
! 28: */
! 29:
! 30: INIT_FUNC(mod_auth_init) {
! 31: mod_auth_plugin_data *p;
! 32:
! 33: p = calloc(1, sizeof(*p));
! 34:
! 35: p->tmp_buf = buffer_init();
! 36:
! 37: p->auth_user = buffer_init();
! 38: #ifdef USE_LDAP
! 39: p->ldap_filter = buffer_init();
! 40: #endif
! 41:
! 42: return p;
! 43: }
! 44:
! 45: FREE_FUNC(mod_auth_free) {
! 46: mod_auth_plugin_data *p = p_d;
! 47:
! 48: UNUSED(srv);
! 49:
! 50: if (!p) return HANDLER_GO_ON;
! 51:
! 52: buffer_free(p->tmp_buf);
! 53: buffer_free(p->auth_user);
! 54: #ifdef USE_LDAP
! 55: buffer_free(p->ldap_filter);
! 56: #endif
! 57:
! 58: if (p->config_storage) {
! 59: size_t i;
! 60: for (i = 0; i < srv->config_context->used; i++) {
! 61: mod_auth_plugin_config *s = p->config_storage[i];
! 62:
! 63: if (!s) continue;
! 64:
! 65: array_free(s->auth_require);
! 66: buffer_free(s->auth_plain_groupfile);
! 67: buffer_free(s->auth_plain_userfile);
! 68: buffer_free(s->auth_htdigest_userfile);
! 69: buffer_free(s->auth_htpasswd_userfile);
! 70: buffer_free(s->auth_backend_conf);
! 71:
! 72: buffer_free(s->auth_ldap_hostname);
! 73: buffer_free(s->auth_ldap_basedn);
! 74: buffer_free(s->auth_ldap_binddn);
! 75: buffer_free(s->auth_ldap_bindpw);
! 76: buffer_free(s->auth_ldap_filter);
! 77: buffer_free(s->auth_ldap_cafile);
! 78:
! 79: #ifdef USE_LDAP
! 80: buffer_free(s->ldap_filter_pre);
! 81: buffer_free(s->ldap_filter_post);
! 82:
! 83: if (s->ldap) ldap_unbind_s(s->ldap);
! 84: #endif
! 85:
! 86: free(s);
! 87: }
! 88: free(p->config_storage);
! 89: }
! 90:
! 91: free(p);
! 92:
! 93: return HANDLER_GO_ON;
! 94: }
! 95:
! 96: #define PATCH(x) \
! 97: p->conf.x = s->x;
! 98: static int mod_auth_patch_connection(server *srv, connection *con, mod_auth_plugin_data *p) {
! 99: size_t i, j;
! 100: mod_auth_plugin_config *s = p->config_storage[0];
! 101:
! 102: PATCH(auth_backend);
! 103: PATCH(auth_plain_groupfile);
! 104: PATCH(auth_plain_userfile);
! 105: PATCH(auth_htdigest_userfile);
! 106: PATCH(auth_htpasswd_userfile);
! 107: PATCH(auth_require);
! 108: PATCH(auth_debug);
! 109: PATCH(auth_ldap_hostname);
! 110: PATCH(auth_ldap_basedn);
! 111: PATCH(auth_ldap_binddn);
! 112: PATCH(auth_ldap_bindpw);
! 113: PATCH(auth_ldap_filter);
! 114: PATCH(auth_ldap_cafile);
! 115: PATCH(auth_ldap_starttls);
! 116: PATCH(auth_ldap_allow_empty_pw);
! 117: #ifdef USE_LDAP
! 118: p->anon_conf = s;
! 119: PATCH(ldap_filter_pre);
! 120: PATCH(ldap_filter_post);
! 121: #endif
! 122:
! 123: /* skip the first, the global context */
! 124: for (i = 1; i < srv->config_context->used; i++) {
! 125: data_config *dc = (data_config *)srv->config_context->data[i];
! 126: s = p->config_storage[i];
! 127:
! 128: /* condition didn't match */
! 129: if (!config_check_cond(srv, con, dc)) continue;
! 130:
! 131: /* merge config */
! 132: for (j = 0; j < dc->value->used; j++) {
! 133: data_unset *du = dc->value->data[j];
! 134:
! 135: if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend"))) {
! 136: PATCH(auth_backend);
! 137: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.groupfile"))) {
! 138: PATCH(auth_plain_groupfile);
! 139: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.plain.userfile"))) {
! 140: PATCH(auth_plain_userfile);
! 141: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htdigest.userfile"))) {
! 142: PATCH(auth_htdigest_userfile);
! 143: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.htpasswd.userfile"))) {
! 144: PATCH(auth_htpasswd_userfile);
! 145: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.require"))) {
! 146: PATCH(auth_require);
! 147: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.debug"))) {
! 148: PATCH(auth_debug);
! 149: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.hostname"))) {
! 150: PATCH(auth_ldap_hostname);
! 151: #ifdef USE_LDAP
! 152: p->anon_conf = s;
! 153: #endif
! 154: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.base-dn"))) {
! 155: PATCH(auth_ldap_basedn);
! 156: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.filter"))) {
! 157: PATCH(auth_ldap_filter);
! 158: #ifdef USE_LDAP
! 159: PATCH(ldap_filter_pre);
! 160: PATCH(ldap_filter_post);
! 161: #endif
! 162: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.ca-file"))) {
! 163: PATCH(auth_ldap_cafile);
! 164: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
! 165: PATCH(auth_ldap_starttls);
! 166: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.bind-dn"))) {
! 167: PATCH(auth_ldap_binddn);
! 168: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.bind-pw"))) {
! 169: PATCH(auth_ldap_bindpw);
! 170: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.allow-empty-pw"))) {
! 171: PATCH(auth_ldap_allow_empty_pw);
! 172: }
! 173: }
! 174: }
! 175:
! 176: return 0;
! 177: }
! 178: #undef PATCH
! 179:
! 180: static handler_t mod_auth_uri_handler(server *srv, connection *con, void *p_d) {
! 181: size_t k;
! 182: int auth_required = 0, auth_satisfied = 0;
! 183: char *http_authorization = NULL;
! 184: const char *auth_type = NULL;
! 185: data_string *ds;
! 186: mod_auth_plugin_data *p = p_d;
! 187: array *req;
! 188: data_string *req_method;
! 189:
! 190: /* select the right config */
! 191: mod_auth_patch_connection(srv, con, p);
! 192:
! 193: if (p->conf.auth_require == NULL) return HANDLER_GO_ON;
! 194:
! 195: /*
! 196: * AUTH
! 197: *
! 198: */
! 199:
! 200: /* do we have to ask for auth ? */
! 201:
! 202: auth_required = 0;
! 203: auth_satisfied = 0;
! 204:
! 205: /* search auth-directives for path */
! 206: for (k = 0; k < p->conf.auth_require->used; k++) {
! 207: buffer *require = p->conf.auth_require->data[k]->key;
! 208:
! 209: if (require->used == 0) continue;
! 210: if (con->uri.path->used < require->used) continue;
! 211:
! 212: /* if we have a case-insensitive FS we have to lower-case the URI here too */
! 213:
! 214: if (con->conf.force_lowercase_filenames) {
! 215: if (0 == strncasecmp(con->uri.path->ptr, require->ptr, require->used - 1)) {
! 216: auth_required = 1;
! 217: break;
! 218: }
! 219: } else {
! 220: if (0 == strncmp(con->uri.path->ptr, require->ptr, require->used - 1)) {
! 221: auth_required = 1;
! 222: break;
! 223: }
! 224: }
! 225: }
! 226:
! 227: /* nothing to do for us */
! 228: if (auth_required == 0) return HANDLER_GO_ON;
! 229:
! 230: req = ((data_array *)(p->conf.auth_require->data[k]))->value;
! 231: req_method = (data_string *)array_get_element(req, "method");
! 232:
! 233: if (0 == strcmp(req_method->value->ptr, "extern")) {
! 234: /* require REMOTE_USER to be already set */
! 235: if (NULL == (ds = (data_string *)array_get_element(con->environment, "REMOTE_USER"))) {
! 236: con->http_status = 401;
! 237: con->mode = DIRECT;
! 238: return HANDLER_FINISHED;
! 239: } else if (http_auth_match_rules(srv, req, ds->value->ptr, NULL, NULL)) {
! 240: log_error_write(srv, __FILE__, __LINE__, "s", "rules didn't match");
! 241: con->http_status = 401;
! 242: con->mode = DIRECT;
! 243: return HANDLER_FINISHED;
! 244: } else {
! 245: return HANDLER_GO_ON;
! 246: }
! 247: }
! 248:
! 249: /* try to get Authorization-header */
! 250:
! 251: if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization")) && ds->value->used) {
! 252: char *auth_realm;
! 253:
! 254: http_authorization = ds->value->ptr;
! 255:
! 256: /* parse auth-header */
! 257: if (NULL != (auth_realm = strchr(http_authorization, ' '))) {
! 258: int auth_type_len = auth_realm - http_authorization;
! 259:
! 260: if ((auth_type_len == 5) &&
! 261: (0 == strncasecmp(http_authorization, "Basic", auth_type_len))) {
! 262: auth_type = "Basic";
! 263:
! 264: if (0 == strcmp(req_method->value->ptr, "basic")) {
! 265: auth_satisfied = http_auth_basic_check(srv, con, p, req, auth_realm+1);
! 266: }
! 267: } else if ((auth_type_len == 6) &&
! 268: (0 == strncasecmp(http_authorization, "Digest", auth_type_len))) {
! 269: auth_type = "Digest";
! 270: if (0 == strcmp(req_method->value->ptr, "digest")) {
! 271: if (-1 == (auth_satisfied = http_auth_digest_check(srv, con, p, req, auth_realm+1))) {
! 272: con->http_status = 400;
! 273: con->mode = DIRECT;
! 274:
! 275: /* a field was missing */
! 276:
! 277: return HANDLER_FINISHED;
! 278: }
! 279: }
! 280: } else {
! 281: log_error_write(srv, __FILE__, __LINE__, "ss",
! 282: "unknown authentification type:",
! 283: http_authorization);
! 284: }
! 285: }
! 286: }
! 287:
! 288: if (!auth_satisfied) {
! 289: data_string *method, *realm;
! 290: method = (data_string *)array_get_element(req, "method");
! 291: realm = (data_string *)array_get_element(req, "realm");
! 292:
! 293: con->http_status = 401;
! 294: con->mode = DIRECT;
! 295:
! 296: if (0 == strcmp(method->value->ptr, "basic")) {
! 297: buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("Basic realm=\""));
! 298: buffer_append_string_buffer(p->tmp_buf, realm->value);
! 299: buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\""));
! 300:
! 301: response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
! 302: } else if (0 == strcmp(method->value->ptr, "digest")) {
! 303: char hh[33];
! 304: http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh);
! 305:
! 306: buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("Digest realm=\""));
! 307: buffer_append_string_buffer(p->tmp_buf, realm->value);
! 308: buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", nonce=\""));
! 309: buffer_append_string(p->tmp_buf, hh);
! 310: buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", qop=\"auth\""));
! 311:
! 312: response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf));
! 313: } else {
! 314: /* evil */
! 315: }
! 316: return HANDLER_FINISHED;
! 317: } else {
! 318: /* the REMOTE_USER header */
! 319:
! 320: if (NULL == (ds = (data_string *)array_get_element(con->environment, "REMOTE_USER"))) {
! 321: if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
! 322: ds = data_string_init();
! 323: }
! 324: buffer_copy_string(ds->key, "REMOTE_USER");
! 325: array_insert_unique(con->environment, (data_unset *)ds);
! 326: }
! 327: buffer_copy_string_buffer(ds->value, p->auth_user);
! 328:
! 329: /* AUTH_TYPE environment */
! 330:
! 331: if (NULL == (ds = (data_string *)array_get_element(con->environment, "AUTH_TYPE"))) {
! 332: if (NULL == (ds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) {
! 333: ds = data_string_init();
! 334: }
! 335: buffer_copy_string(ds->key, "AUTH_TYPE");
! 336: array_insert_unique(con->environment, (data_unset *)ds);
! 337: }
! 338: buffer_copy_string(ds->value, auth_type);
! 339: }
! 340:
! 341: return HANDLER_GO_ON;
! 342: }
! 343:
! 344: SETDEFAULTS_FUNC(mod_auth_set_defaults) {
! 345: mod_auth_plugin_data *p = p_d;
! 346: size_t i;
! 347:
! 348: config_values_t cv[] = {
! 349: { "auth.backend", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
! 350: { "auth.backend.plain.groupfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
! 351: { "auth.backend.plain.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
! 352: { "auth.require", NULL, T_CONFIG_LOCAL, T_CONFIG_SCOPE_CONNECTION }, /* 3 */
! 353: { "auth.backend.ldap.hostname", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 4 */
! 354: { "auth.backend.ldap.base-dn", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 5 */
! 355: { "auth.backend.ldap.filter", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 6 */
! 356: { "auth.backend.ldap.ca-file", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 7 */
! 357: { "auth.backend.ldap.starttls", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */
! 358: { "auth.backend.ldap.bind-dn", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 9 */
! 359: { "auth.backend.ldap.bind-pw", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
! 360: { "auth.backend.ldap.allow-empty-pw", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 11 */
! 361: { "auth.backend.htdigest.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 12 */
! 362: { "auth.backend.htpasswd.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 13 */
! 363: { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 14 */
! 364: { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
! 365: };
! 366:
! 367: p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
! 368:
! 369: for (i = 0; i < srv->config_context->used; i++) {
! 370: mod_auth_plugin_config *s;
! 371: size_t n;
! 372: data_array *da;
! 373: array *ca;
! 374:
! 375: s = calloc(1, sizeof(mod_auth_plugin_config));
! 376: s->auth_plain_groupfile = buffer_init();
! 377: s->auth_plain_userfile = buffer_init();
! 378: s->auth_htdigest_userfile = buffer_init();
! 379: s->auth_htpasswd_userfile = buffer_init();
! 380: s->auth_backend_conf = buffer_init();
! 381:
! 382: s->auth_ldap_hostname = buffer_init();
! 383: s->auth_ldap_basedn = buffer_init();
! 384: s->auth_ldap_binddn = buffer_init();
! 385: s->auth_ldap_bindpw = buffer_init();
! 386: s->auth_ldap_filter = buffer_init();
! 387: s->auth_ldap_cafile = buffer_init();
! 388: s->auth_ldap_starttls = 0;
! 389: s->auth_debug = 0;
! 390:
! 391: s->auth_require = array_init();
! 392:
! 393: #ifdef USE_LDAP
! 394: s->ldap_filter_pre = buffer_init();
! 395: s->ldap_filter_post = buffer_init();
! 396: s->ldap = NULL;
! 397: #endif
! 398:
! 399: cv[0].destination = s->auth_backend_conf;
! 400: cv[1].destination = s->auth_plain_groupfile;
! 401: cv[2].destination = s->auth_plain_userfile;
! 402: cv[3].destination = s->auth_require;
! 403: cv[4].destination = s->auth_ldap_hostname;
! 404: cv[5].destination = s->auth_ldap_basedn;
! 405: cv[6].destination = s->auth_ldap_filter;
! 406: cv[7].destination = s->auth_ldap_cafile;
! 407: cv[8].destination = &(s->auth_ldap_starttls);
! 408: cv[9].destination = s->auth_ldap_binddn;
! 409: cv[10].destination = s->auth_ldap_bindpw;
! 410: cv[11].destination = &(s->auth_ldap_allow_empty_pw);
! 411: cv[12].destination = s->auth_htdigest_userfile;
! 412: cv[13].destination = s->auth_htpasswd_userfile;
! 413: cv[14].destination = &(s->auth_debug);
! 414:
! 415: p->config_storage[i] = s;
! 416: ca = ((data_config *)srv->config_context->data[i])->value;
! 417:
! 418: if (0 != config_insert_values_global(srv, ca, cv)) {
! 419: return HANDLER_ERROR;
! 420: }
! 421:
! 422: if (s->auth_backend_conf->used) {
! 423: if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) {
! 424: s->auth_backend = AUTH_BACKEND_HTPASSWD;
! 425: } else if (0 == strcmp(s->auth_backend_conf->ptr, "htdigest")) {
! 426: s->auth_backend = AUTH_BACKEND_HTDIGEST;
! 427: } else if (0 == strcmp(s->auth_backend_conf->ptr, "plain")) {
! 428: s->auth_backend = AUTH_BACKEND_PLAIN;
! 429: } else if (0 == strcmp(s->auth_backend_conf->ptr, "ldap")) {
! 430: s->auth_backend = AUTH_BACKEND_LDAP;
! 431: } else {
! 432: log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf);
! 433:
! 434: return HANDLER_ERROR;
! 435: }
! 436: }
! 437:
! 438: #ifdef USE_LDAP
! 439: if (s->auth_ldap_filter->used) {
! 440: char *dollar;
! 441:
! 442: /* parse filter */
! 443:
! 444: if (NULL == (dollar = strchr(s->auth_ldap_filter->ptr, '$'))) {
! 445: log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.filter is missing a replace-operator '$'");
! 446:
! 447: return HANDLER_ERROR;
! 448: }
! 449:
! 450: buffer_copy_string_len(s->ldap_filter_pre, s->auth_ldap_filter->ptr, dollar - s->auth_ldap_filter->ptr);
! 451: buffer_copy_string(s->ldap_filter_post, dollar+1);
! 452: }
! 453: #endif
! 454:
! 455: /* no auth.require for this section */
! 456: if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue;
! 457:
! 458: if (da->type != TYPE_ARRAY) continue;
! 459:
! 460: for (n = 0; n < da->value->used; n++) {
! 461: size_t m;
! 462: data_array *da_file = (data_array *)da->value->data[n];
! 463: const char *method, *realm, *require;
! 464:
! 465: if (da->value->data[n]->type != TYPE_ARRAY) {
! 466: log_error_write(srv, __FILE__, __LINE__, "ss",
! 467: "auth.require should contain an array as in:",
! 468: "auth.require = ( \"...\" => ( ..., ...) )");
! 469:
! 470: return HANDLER_ERROR;
! 471: }
! 472:
! 473: method = realm = require = NULL;
! 474:
! 475: for (m = 0; m < da_file->value->used; m++) {
! 476: if (da_file->value->data[m]->type == TYPE_STRING) {
! 477: if (0 == strcmp(da_file->value->data[m]->key->ptr, "method")) {
! 478: method = ((data_string *)(da_file->value->data[m]))->value->ptr;
! 479: } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "realm")) {
! 480: realm = ((data_string *)(da_file->value->data[m]))->value->ptr;
! 481: } else if (0 == strcmp(da_file->value->data[m]->key->ptr, "require")) {
! 482: require = ((data_string *)(da_file->value->data[m]))->value->ptr;
! 483: } else {
! 484: log_error_write(srv, __FILE__, __LINE__, "ssbs",
! 485: "the field is unknown in:",
! 486: "auth.require = ( \"...\" => ( ..., -> \"",
! 487: da_file->value->data[m]->key,
! 488: "\" <- => \"...\" ) )");
! 489:
! 490: return HANDLER_ERROR;
! 491: }
! 492: } else {
! 493: log_error_write(srv, __FILE__, __LINE__, "ssbs",
! 494: "a string was expected for:",
! 495: "auth.require = ( \"...\" => ( ..., -> \"",
! 496: da_file->value->data[m]->key,
! 497: "\" <- => \"...\" ) )");
! 498:
! 499: return HANDLER_ERROR;
! 500: }
! 501: }
! 502:
! 503: if (method == NULL) {
! 504: log_error_write(srv, __FILE__, __LINE__, "ss",
! 505: "the method field is missing in:",
! 506: "auth.require = ( \"...\" => ( ..., \"method\" => \"...\" ) )");
! 507: return HANDLER_ERROR;
! 508: } else {
! 509: if (0 != strcmp(method, "basic") &&
! 510: 0 != strcmp(method, "digest") &&
! 511: 0 != strcmp(method, "extern")) {
! 512: log_error_write(srv, __FILE__, __LINE__, "ss",
! 513: "method has to be either \"basic\", \"digest\" or \"extern\" in",
! 514: "auth.require = ( \"...\" => ( ..., \"method\" => \"...\") )");
! 515: return HANDLER_ERROR;
! 516: }
! 517: }
! 518:
! 519: if (realm == NULL) {
! 520: log_error_write(srv, __FILE__, __LINE__, "ss",
! 521: "the realm field is missing in:",
! 522: "auth.require = ( \"...\" => ( ..., \"realm\" => \"...\" ) )");
! 523: return HANDLER_ERROR;
! 524: }
! 525:
! 526: if (require == NULL) {
! 527: log_error_write(srv, __FILE__, __LINE__, "ss",
! 528: "the require field is missing in:",
! 529: "auth.require = ( \"...\" => ( ..., \"require\" => \"...\" ) )");
! 530: return HANDLER_ERROR;
! 531: }
! 532:
! 533: if (method && realm && require) {
! 534: data_string *ds;
! 535: data_array *a;
! 536:
! 537: a = data_array_init();
! 538: buffer_copy_string_buffer(a->key, da_file->key);
! 539:
! 540: ds = data_string_init();
! 541:
! 542: buffer_copy_string_len(ds->key, CONST_STR_LEN("method"));
! 543: buffer_copy_string(ds->value, method);
! 544:
! 545: array_insert_unique(a->value, (data_unset *)ds);
! 546:
! 547: ds = data_string_init();
! 548:
! 549: buffer_copy_string_len(ds->key, CONST_STR_LEN("realm"));
! 550: buffer_copy_string(ds->value, realm);
! 551:
! 552: array_insert_unique(a->value, (data_unset *)ds);
! 553:
! 554: ds = data_string_init();
! 555:
! 556: buffer_copy_string_len(ds->key, CONST_STR_LEN("require"));
! 557: buffer_copy_string(ds->value, require);
! 558:
! 559: array_insert_unique(a->value, (data_unset *)ds);
! 560:
! 561: array_insert_unique(s->auth_require, (data_unset *)a);
! 562: }
! 563: }
! 564:
! 565: switch(s->auth_ldap_hostname->used) {
! 566: case AUTH_BACKEND_LDAP: {
! 567: handler_t ret = auth_ldap_init(srv, s);
! 568: if (ret == HANDLER_ERROR)
! 569: return (ret);
! 570: break;
! 571: }
! 572: default:
! 573: break;
! 574: }
! 575: }
! 576:
! 577: return HANDLER_GO_ON;
! 578: }
! 579:
! 580: handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s) {
! 581: #ifdef USE_LDAP
! 582: int ret;
! 583: #if 0
! 584: if (s->auth_ldap_basedn->used == 0) {
! 585: log_error_write(srv, __FILE__, __LINE__, "s", "ldap: auth.backend.ldap.base-dn has to be set");
! 586:
! 587: return HANDLER_ERROR;
! 588: }
! 589: #endif
! 590:
! 591: if (s->auth_ldap_hostname->used) {
! 592: /* free old context */
! 593: if (NULL != s->ldap) ldap_unbind_s(s->ldap);
! 594:
! 595: if (NULL == (s->ldap = ldap_init(s->auth_ldap_hostname->ptr, LDAP_PORT))) {
! 596: log_error_write(srv, __FILE__, __LINE__, "ss", "ldap ...", strerror(errno));
! 597:
! 598: return HANDLER_ERROR;
! 599: }
! 600:
! 601: ret = LDAP_VERSION3;
! 602: if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(s->ldap, LDAP_OPT_PROTOCOL_VERSION, &ret))) {
! 603: log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
! 604:
! 605: return HANDLER_ERROR;
! 606: }
! 607:
! 608: if (s->auth_ldap_starttls) {
! 609: /* if no CA file is given, it is ok, as we will use encryption
! 610: * if the server requires a CAfile it will tell us */
! 611: if (!buffer_is_empty(s->auth_ldap_cafile)) {
! 612: if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE,
! 613: s->auth_ldap_cafile->ptr))) {
! 614: log_error_write(srv, __FILE__, __LINE__, "ss",
! 615: "Loading CA certificate failed:", ldap_err2string(ret));
! 616:
! 617: return HANDLER_ERROR;
! 618: }
! 619: }
! 620:
! 621: if (LDAP_OPT_SUCCESS != (ret = ldap_start_tls_s(s->ldap, NULL, NULL))) {
! 622: log_error_write(srv, __FILE__, __LINE__, "ss", "ldap startTLS failed:", ldap_err2string(ret));
! 623:
! 624: return HANDLER_ERROR;
! 625: }
! 626: }
! 627:
! 628:
! 629: /* 1. */
! 630: if (s->auth_ldap_binddn->used) {
! 631: if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) {
! 632: log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
! 633:
! 634: return HANDLER_ERROR;
! 635: }
! 636: } else {
! 637: if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, NULL, NULL))) {
! 638: log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));
! 639:
! 640: return HANDLER_ERROR;
! 641: }
! 642: }
! 643: }
! 644: return HANDLER_GO_ON;
! 645: #else
! 646: UNUSED(s);
! 647: log_error_write(srv, __FILE__, __LINE__, "s", "no ldap support available");
! 648: return HANDLER_ERROR;
! 649: #endif
! 650: }
! 651:
! 652: int mod_auth_plugin_init(plugin *p);
! 653: int mod_auth_plugin_init(plugin *p) {
! 654: p->version = LIGHTTPD_VERSION_ID;
! 655: p->name = buffer_init_string("auth");
! 656: p->init = mod_auth_init;
! 657: p->set_defaults = mod_auth_set_defaults;
! 658: p->handle_uri_clean = mod_auth_uri_handler;
! 659: p->cleanup = mod_auth_free;
! 660:
! 661: p->data = NULL;
! 662:
! 663: return 0;
! 664: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>