--- embedaddon/lighttpd/src/mod_auth.c 2014/06/15 20:20:06 1.1.1.2 +++ embedaddon/lighttpd/src/mod_auth.c 2016/11/02 10:35:00 1.1.1.3 @@ -1,3 +1,5 @@ +#include "first.h" + #include "plugin.h" #include "http_auth.h" #include "log.h" @@ -11,6 +13,7 @@ #include #include #include +#include handler_t auth_ldap_init(server *srv, mod_auth_plugin_config *s); @@ -60,7 +63,7 @@ FREE_FUNC(mod_auth_free) { for (i = 0; i < srv->config_context->used; i++) { mod_auth_plugin_config *s = p->config_storage[i]; - if (!s) continue; + if (NULL == s) continue; array_free(s->auth_require); buffer_free(s->auth_plain_groupfile); @@ -82,6 +85,19 @@ FREE_FUNC(mod_auth_free) { if (s->ldap) ldap_unbind_s(s->ldap); #endif + buffer_free(s->auth_mysql_host); + buffer_free(s->auth_mysql_user); + buffer_free(s->auth_mysql_pass); + buffer_free(s->auth_mysql_db); + buffer_free(s->auth_mysql_socket); + buffer_free(s->auth_mysql_users_table); + buffer_free(s->auth_mysql_col_user); + buffer_free(s->auth_mysql_col_pass); + buffer_free(s->auth_mysql_col_realm); + buffer_free(s->auth_mysql_domains_table); + buffer_free(s->auth_mysql_col_domain); + buffer_free(s->auth_mysql_domains_table_col_domain_id); + buffer_free(s->auth_mysql_users_table_col_domain_id); free(s); } @@ -120,6 +136,21 @@ static int mod_auth_patch_connection(server *srv, conn PATCH(ldap_filter_post); #endif + PATCH(auth_mysql_host); + PATCH(auth_mysql_user); + PATCH(auth_mysql_pass); + PATCH(auth_mysql_db); + PATCH(auth_mysql_port); + PATCH(auth_mysql_socket); + PATCH(auth_mysql_users_table); + PATCH(auth_mysql_col_user); + PATCH(auth_mysql_col_pass); + PATCH(auth_mysql_col_realm); + PATCH(auth_mysql_domains_table); + PATCH(auth_mysql_col_domain); + PATCH(auth_mysql_domains_table_col_domain_id); + PATCH(auth_mysql_users_table_col_domain_id); + /* skip the first, the global context */ for (i = 1; i < srv->config_context->used; i++) { data_config *dc = (data_config *)srv->config_context->data[i]; @@ -169,6 +200,34 @@ static int mod_auth_patch_connection(server *srv, conn PATCH(auth_ldap_bindpw); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.allow-empty-pw"))) { PATCH(auth_ldap_allow_empty_pw); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.host"))) { + PATCH(auth_mysql_host); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.user"))) { + PATCH(auth_mysql_user); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.pass"))) { + PATCH(auth_mysql_pass); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.db"))) { + PATCH(auth_mysql_db); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.port"))) { + PATCH(auth_mysql_port); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.socket"))) { + PATCH(auth_mysql_user); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.users_table"))) { + PATCH(auth_mysql_users_table); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.col_user"))) { + PATCH(auth_mysql_col_user); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.col_pass"))) { + PATCH(auth_mysql_col_pass); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.col_realm"))) { + PATCH(auth_mysql_col_realm); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.domains_table"))) { + PATCH(auth_mysql_domains_table); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.col_domain"))) { + PATCH(auth_mysql_col_domain); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.domains_table_col_domain_id"))) { + PATCH(auth_mysql_domains_table_col_domain_id); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.mysql.users_table_col_domain_id"))) { + PATCH(auth_mysql_users_table_col_domain_id); } } } @@ -206,18 +265,18 @@ static handler_t mod_auth_uri_handler(server *srv, con for (k = 0; k < p->conf.auth_require->used; k++) { buffer *require = p->conf.auth_require->data[k]->key; - if (require->used == 0) continue; - if (con->uri.path->used < require->used) continue; + if (buffer_is_empty(require)) continue; + if (buffer_string_length(con->uri.path) < buffer_string_length(require)) continue; /* if we have a case-insensitive FS we have to lower-case the URI here too */ if (con->conf.force_lowercase_filenames) { - if (0 == strncasecmp(con->uri.path->ptr, require->ptr, require->used - 1)) { + if (0 == strncasecmp(con->uri.path->ptr, require->ptr, buffer_string_length(require))) { auth_required = 1; break; } } else { - if (0 == strncmp(con->uri.path->ptr, require->ptr, require->used - 1)) { + if (0 == strncmp(con->uri.path->ptr, require->ptr, buffer_string_length(require))) { auth_required = 1; break; } @@ -248,7 +307,7 @@ static handler_t mod_auth_uri_handler(server *srv, con /* try to get Authorization-header */ - if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization")) && ds->value->used) { + if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Authorization")) && !buffer_is_empty(ds->value)) { char *auth_realm; http_authorization = ds->value->ptr; @@ -279,13 +338,13 @@ static handler_t mod_auth_uri_handler(server *srv, con } } else { log_error_write(srv, __FILE__, __LINE__, "ss", - "unknown authentification type:", + "unknown authentication type:", http_authorization); } } } - if (!auth_satisfied) { + if (1 != auth_satisfied) { /*(0 or -2)*/ data_string *method, *realm; method = (data_string *)array_get_element(req, "method"); realm = (data_string *)array_get_element(req, "realm"); @@ -293,21 +352,29 @@ static handler_t mod_auth_uri_handler(server *srv, con con->http_status = 401; con->mode = DIRECT; + if (!method) return HANDLER_FINISHED;/*(should not happen; config is validated at startup)*/ + if (!realm) return HANDLER_FINISHED; /*(should not happen; config is validated at startup)*/ + if (0 == strcmp(method->value->ptr, "basic")) { buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("Basic realm=\"")); buffer_append_string_buffer(p->tmp_buf, realm->value); - buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\"")); + buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", charset=\"UTF-8\"")); response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf)); } else if (0 == strcmp(method->value->ptr, "digest")) { char hh[33]; - http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, hh); + http_auth_digest_generate_nonce(srv, p, srv->tmp_buf, &hh); buffer_copy_string_len(p->tmp_buf, CONST_STR_LEN("Digest realm=\"")); buffer_append_string_buffer(p->tmp_buf, realm->value); - buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", nonce=\"")); + buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", charset=\"UTF-8\", nonce=\"")); + buffer_append_uint_hex(p->tmp_buf, (uintmax_t)srv->cur_ts); + buffer_append_string_len(p->tmp_buf, CONST_STR_LEN(":")); buffer_append_string(p->tmp_buf, hh); buffer_append_string_len(p->tmp_buf, CONST_STR_LEN("\", qop=\"auth\"")); + if (-2 == auth_satisfied) { + buffer_append_string_len(p->tmp_buf, CONST_STR_LEN(", stale=true")); + } response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf)); } else { @@ -324,7 +391,7 @@ static handler_t mod_auth_uri_handler(server *srv, con buffer_copy_string(ds->key, "REMOTE_USER"); array_insert_unique(con->environment, (data_unset *)ds); } - buffer_copy_string_buffer(ds->value, p->auth_user); + buffer_copy_buffer(ds->value, p->auth_user); /* AUTH_TYPE environment */ @@ -357,20 +424,35 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { { "auth.backend.ldap.starttls", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 8 */ { "auth.backend.ldap.bind-dn", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 9 */ { "auth.backend.ldap.bind-pw", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 10 */ - { "auth.backend.ldap.allow-empty-pw", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 11 */ + { "auth.backend.ldap.allow-empty-pw", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, { "auth.backend.htdigest.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 12 */ { "auth.backend.htpasswd.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 13 */ { "auth.debug", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION }, /* 14 */ + { "auth.backend.mysql.host", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.db", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.port", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.socket", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.users_table", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.col_user", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.col_pass", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.col_realm", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 23 */ + { "auth.backend.mysql.domains_table", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.col_domain", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.domains_table_col_domain_id", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, + { "auth.backend.mysql.users_table_col_domain_id", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 27 */ + { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET } }; p->config_storage = calloc(1, srv->config_context->used * sizeof(mod_auth_plugin_config *)); for (i = 0; i < srv->config_context->used; i++) { + data_config const* config = (data_config const*)srv->config_context->data[i]; mod_auth_plugin_config *s; size_t n; data_array *da; - array *ca; s = calloc(1, sizeof(mod_auth_plugin_config)); s->auth_plain_groupfile = buffer_init(); @@ -389,7 +471,23 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { s->auth_debug = 0; s->auth_require = array_init(); + s->mysql_conn = NULL; + s->auth_mysql_host = buffer_init(); + s->auth_mysql_user = buffer_init(); + s->auth_mysql_pass = buffer_init(); + s->auth_mysql_db = buffer_init(); + s->auth_mysql_port = buffer_init(); + s->auth_mysql_socket = buffer_init(); + s->auth_mysql_users_table = buffer_init(); + s->auth_mysql_col_user = buffer_init(); + s->auth_mysql_col_pass = buffer_init(); + s->auth_mysql_col_realm = buffer_init(); + s->auth_mysql_domains_table = buffer_init(); + s->auth_mysql_col_domain = buffer_init(); + s->auth_mysql_domains_table_col_domain_id = buffer_init(); + s->auth_mysql_users_table_col_domain_id = buffer_init(); + #ifdef USE_LDAP s->ldap_filter_pre = buffer_init(); s->ldap_filter_post = buffer_init(); @@ -411,15 +509,27 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { cv[12].destination = s->auth_htdigest_userfile; cv[13].destination = s->auth_htpasswd_userfile; cv[14].destination = &(s->auth_debug); - + cv[15].destination = s->auth_mysql_host; + cv[16].destination = s->auth_mysql_user; + cv[17].destination = s->auth_mysql_pass; + cv[18].destination = s->auth_mysql_db; + cv[19].destination = s->auth_mysql_port; + cv[20].destination = s->auth_mysql_socket; + cv[21].destination = s->auth_mysql_users_table; + cv[22].destination = s->auth_mysql_col_user; + cv[23].destination = s->auth_mysql_col_pass; + cv[24].destination = s->auth_mysql_col_realm; + cv[25].destination = s->auth_mysql_domains_table; + cv[26].destination = s->auth_mysql_col_domain; + cv[27].destination = s->auth_mysql_domains_table_col_domain_id; + cv[28].destination = s->auth_mysql_users_table_col_domain_id; p->config_storage[i] = s; - ca = ((data_config *)srv->config_context->data[i])->value; - if (0 != config_insert_values_global(srv, ca, cv)) { + if (0 != config_insert_values_global(srv, config->value, cv, i == 0 ? T_CONFIG_SCOPE_SERVER : T_CONFIG_SCOPE_CONNECTION)) { return HANDLER_ERROR; } - if (s->auth_backend_conf->used) { + if (!buffer_string_is_empty(s->auth_backend_conf)) { if (0 == strcmp(s->auth_backend_conf->ptr, "htpasswd")) { s->auth_backend = AUTH_BACKEND_HTPASSWD; } else if (0 == strcmp(s->auth_backend_conf->ptr, "htdigest")) { @@ -428,6 +538,8 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { s->auth_backend = AUTH_BACKEND_PLAIN; } else if (0 == strcmp(s->auth_backend_conf->ptr, "ldap")) { s->auth_backend = AUTH_BACKEND_LDAP; + } else if (0 == strcmp(s->auth_backend_conf->ptr, "mysql")) { + s->auth_backend = AUTH_BACKEND_MYSQL; } else { log_error_write(srv, __FILE__, __LINE__, "sb", "auth.backend not supported:", s->auth_backend_conf); @@ -436,7 +548,7 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { } #ifdef USE_LDAP - if (s->auth_ldap_filter->used) { + if (!buffer_string_is_empty(s->auth_ldap_filter)) { char *dollar; /* parse filter */ @@ -453,7 +565,7 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { #endif /* no auth.require for this section */ - if (NULL == (da = (data_array *)array_get_element(ca, "auth.require"))) continue; + if (NULL == (da = (data_array *)array_get_element(config->value, "auth.require"))) continue; if (da->type != TYPE_ARRAY) continue; @@ -535,7 +647,7 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { data_array *a; a = data_array_init(); - buffer_copy_string_buffer(a->key, da_file->key); + buffer_copy_buffer(a->key, da_file->key); ds = data_string_init(); @@ -562,13 +674,38 @@ SETDEFAULTS_FUNC(mod_auth_set_defaults) { } } - switch(s->auth_ldap_hostname->used) { + switch(s->auth_backend) { case AUTH_BACKEND_LDAP: { handler_t ret = auth_ldap_init(srv, s); if (ret == HANDLER_ERROR) return (ret); break; } + case AUTH_BACKEND_MYSQL: { + int port = atoi(s->auth_mysql_port->ptr); + + /* ignore if auth_mysql_socket is invalid */ + if (p->conf.auth_mysql_socket == NULL) + return HANDLER_GO_ON; + if (p->conf.auth_mysql_socket->ptr != NULL) + if (0 == strcmp(s->auth_mysql_socket->ptr, "")) s->auth_mysql_socket->ptr = NULL; + + s->mysql_conn = mysql_init(NULL); + if (!mysql_real_connect(s->mysql_conn, s->auth_mysql_host->ptr, s->auth_mysql_user->ptr, s->auth_mysql_pass->ptr, s->auth_mysql_db->ptr, port, NULL, 0)) + { + log_error_write(srv, __FILE__, __LINE__, "sbsbsbsbss", + "opening connection to mysql:", s->auth_mysql_host, + "user:", s->auth_mysql_user, + "pass:", s->auth_mysql_pass, + "db:", s->auth_mysql_db, + "failed:", strerror(errno)); + + return HANDLER_ERROR; + } + mysql_close(s->mysql_conn); + + break; + } default: break; } @@ -588,7 +725,7 @@ handler_t auth_ldap_init(server *srv, mod_auth_plugin_ } #endif - if (s->auth_ldap_hostname->used) { + if (!buffer_string_is_empty(s->auth_ldap_hostname)) { /* free old context */ if (NULL != s->ldap) ldap_unbind_s(s->ldap); @@ -608,7 +745,7 @@ handler_t auth_ldap_init(server *srv, mod_auth_plugin_ if (s->auth_ldap_starttls) { /* if no CA file is given, it is ok, as we will use encryption * if the server requires a CAfile it will tell us */ - if (!buffer_is_empty(s->auth_ldap_cafile)) { + if (!buffer_string_is_empty(s->auth_ldap_cafile)) { if (LDAP_OPT_SUCCESS != (ret = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, s->auth_ldap_cafile->ptr))) { log_error_write(srv, __FILE__, __LINE__, "ss", @@ -627,7 +764,7 @@ handler_t auth_ldap_init(server *srv, mod_auth_plugin_ /* 1. */ - if (s->auth_ldap_binddn->used) { + if (!buffer_string_is_empty(s->auth_ldap_binddn)) { if (LDAP_SUCCESS != (ret = ldap_simple_bind_s(s->ldap, s->auth_ldap_binddn->ptr, s->auth_ldap_bindpw->ptr))) { log_error_write(srv, __FILE__, __LINE__, "ss", "ldap:", ldap_err2string(ret));