├── README ├── config ├── license └── ngx_http_auth_sqlite_basic_module.c /README: -------------------------------------------------------------------------------- 1 | Name 2 | ==== 3 | 4 | sqlite-http-basic-auth-nginx-module - Sqlite based basic authentication for Nginx 5 | 6 | Installation 7 | ============ 8 | 9 | 1. Install sqlite3 into your system. 10 | 11 | 1. Download the latest version of the release tarball of this module from 12 | sqlite-http-basic-auth-nginx-module [file list](http://github.com/kunal/sqlite-http-basic-auth-nginx-module/downloads). 13 | 14 | 1. Grab the nginx source code from [nginx.net](http://nginx.net/), for example, 15 | the version 0.8.54 (see nginx compatibility), and then build the source with 16 | this module: 17 | 18 | $ wget 'http://sysoev.ru/nginx/nginx-0.8.54.tar.gz' 19 | $ tar -xzvf nginx-0.8.54.tar.gz 20 | $ cd nginx-0.8.54/ 21 | 22 | # Here we assume you would install you nginx under /opt/nginx/. 23 | $ ./configure --prefix=/opt/nginx \ 24 | --add-module=/path/to/sqlite-http-basic-auth-nginx-module 25 | 26 | $ make 27 | $ make install 28 | 29 | Usage 30 | ===== 31 | 32 | Add the following to nginx.conf: 33 | 34 | location / { 35 | auth_sqlite_basic "Restricted Sqlite"; 36 | auth_sqlite_basic_database_file /home/kunal/nginx/db/sqlite_db; # Sqlite DB file 37 | auth_sqlite_basic_database_table auth_table; # Sqlite DB table 38 | auth_sqlite_basic_table_user_column user; # User column 39 | auth_sqlite_basic_table_passwd_column password; # Password column 40 | root html; 41 | index index.html index.htm; 42 | } 43 | 44 | 45 | Compatibility 46 | ============= 47 | 48 | The following versions of Nginx should work with this module: 49 | 50 | * 0.8.x (last tested: 0.8.54) 51 | 52 | TODO 53 | ==== 54 | 55 | * Support encrypted passwords 56 | * Support for "where" conditions 57 | 58 | Copyright & License 59 | =================== 60 | 61 | This module is licenced under the BSD license. 62 | 63 | Copyright (C) 2011 by Kunal P.Bharati . 64 | 65 | All rights reserved. 66 | 67 | Redistribution and use in source and binary forms, with or without 68 | modification, are permitted provided that the following conditions 69 | are met: 70 | 71 | * Redistributions of source code must retain the above copyright 72 | notice, this list of conditions and the following disclaimer. 73 | 74 | * Redistributions in binary form must reproduce the above copyright 75 | notice, this list of conditions and the following disclaimer in the 76 | documentation and/or other materials provided with the distribution. 77 | 78 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 79 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 80 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 81 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 82 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 83 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 84 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 85 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 86 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 87 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 88 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 89 | -------------------------------------------------------------------------------- /config: -------------------------------------------------------------------------------- 1 | ngx_addon_name=ngx_http_auth_sqlite_basic_module 2 | HTTP_AUX_FILTER_MODULES="$HTTP_AUX_FILTER_MODULES ngx_http_auth_sqlite_basic_module" 3 | NGX_ADDON_SRCS="$NGX_ADDON_SRCS $ngx_addon_dir/ngx_http_auth_sqlite_basic_module.c" 4 | CORE_LIBS="$CORE_LIBS -lsqlite3" 5 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | This module is licenced under the BSD license. 2 | 3 | Copyright (C) 2011 by Kunal P.Bharati . 4 | 5 | All rights reserved. 6 | 7 | Redistribution and use in source and binary forms, with or without 8 | modification, are permitted provided that the following conditions 9 | are met: 10 | 11 | * Redistributions of source code must retain the above copyright 12 | notice, this list of conditions and the following disclaimer. 13 | 14 | * Redistributions in binary form must reproduce the above copyright 15 | notice, this list of conditions and the following disclaimer in the 16 | documentation and/or other materials provided with the distribution. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 24 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 25 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 26 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 27 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /ngx_http_auth_sqlite_basic_module.c: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | * Copyright (C) Kunal Bharati 4 | */ 5 | 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #define NGX_HTTP_AUTH_BUF_SIZE 2048 13 | 14 | typedef struct { 15 | ngx_str_t realm; 16 | ngx_str_t sqlite_table; 17 | ngx_str_t sqlite_user; 18 | ngx_str_t sqlite_passwd; 19 | ngx_str_t sqlite_db_file; 20 | } ngx_http_auth_sqlite_basic_loc_conf_t; 21 | 22 | 23 | static ngx_int_t ngx_http_auth_sqlite_basic_handler(ngx_http_request_t *r); 24 | static ngx_int_t ngx_http_auth_sqlite_basic_set_realm(ngx_http_request_t *r, 25 | ngx_str_t *realm); 26 | static void *ngx_http_auth_sqlite_basic_create_loc_conf(ngx_conf_t *cf); 27 | static char *ngx_http_auth_sqlite_basic_merge_loc_conf(ngx_conf_t *cf, 28 | void *parent, void *child); 29 | static ngx_int_t ngx_http_auth_sqlite_basic_init(ngx_conf_t *cf); 30 | static char *ngx_http_auth_sqlite_basic(ngx_conf_t *cf, void *post, void *data); 31 | 32 | 33 | static ngx_conf_post_handler_pt ngx_http_auth_sqlite_basic_p = ngx_http_auth_sqlite_basic; 34 | 35 | static ngx_command_t ngx_http_auth_sqlite_basic_commands[] = { 36 | 37 | { ngx_string("auth_sqlite_basic"), 38 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF 39 | |NGX_CONF_TAKE1, 40 | ngx_conf_set_str_slot, 41 | NGX_HTTP_LOC_CONF_OFFSET, 42 | offsetof(ngx_http_auth_sqlite_basic_loc_conf_t, realm), 43 | &ngx_http_auth_sqlite_basic_p }, 44 | 45 | { ngx_string("auth_sqlite_basic_database_file"), 46 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF 47 | |NGX_CONF_TAKE1, 48 | ngx_conf_set_str_slot, 49 | NGX_HTTP_LOC_CONF_OFFSET, 50 | offsetof(ngx_http_auth_sqlite_basic_loc_conf_t, sqlite_db_file), 51 | NULL }, 52 | 53 | { ngx_string("auth_sqlite_basic_database_table"), 54 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF 55 | |NGX_CONF_TAKE1, 56 | ngx_conf_set_str_slot, 57 | NGX_HTTP_LOC_CONF_OFFSET, 58 | offsetof(ngx_http_auth_sqlite_basic_loc_conf_t, sqlite_table), 59 | NULL }, 60 | 61 | { ngx_string("auth_sqlite_basic_table_user_column"), 62 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF 63 | |NGX_CONF_TAKE1, 64 | ngx_conf_set_str_slot, 65 | NGX_HTTP_LOC_CONF_OFFSET, 66 | offsetof(ngx_http_auth_sqlite_basic_loc_conf_t, sqlite_user), 67 | NULL }, 68 | 69 | { ngx_string("auth_sqlite_basic_table_passwd_column"), 70 | NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF 71 | |NGX_CONF_TAKE1, 72 | ngx_conf_set_str_slot, 73 | NGX_HTTP_LOC_CONF_OFFSET, 74 | offsetof(ngx_http_auth_sqlite_basic_loc_conf_t, sqlite_passwd), 75 | NULL }, 76 | 77 | ngx_null_command 78 | }; 79 | 80 | 81 | static ngx_http_module_t ngx_http_auth_sqlite_basic_module_ctx = { 82 | NULL, /* preconfiguration */ 83 | ngx_http_auth_sqlite_basic_init, /* postconfiguration */ 84 | 85 | NULL, /* create main configuration */ 86 | NULL, /* init main configuration */ 87 | 88 | NULL, /* create server configuration */ 89 | NULL, /* merge server configuration */ 90 | 91 | ngx_http_auth_sqlite_basic_create_loc_conf, /* create location configuration */ 92 | ngx_http_auth_sqlite_basic_merge_loc_conf /* merge location configuration */ 93 | }; 94 | 95 | 96 | ngx_module_t ngx_http_auth_sqlite_basic_module = { 97 | NGX_MODULE_V1, 98 | &ngx_http_auth_sqlite_basic_module_ctx, /* module context */ 99 | ngx_http_auth_sqlite_basic_commands, /* module directives */ 100 | NGX_HTTP_MODULE, /* module type */ 101 | NULL, /* init master */ 102 | NULL, /* init module */ 103 | NULL, /* init process */ 104 | NULL, /* init thread */ 105 | NULL, /* exit thread */ 106 | NULL, /* exit process */ 107 | NULL, /* exit master */ 108 | NGX_MODULE_V1_PADDING 109 | }; 110 | 111 | 112 | static ngx_int_t 113 | ngx_http_auth_sqlite_basic_handler(ngx_http_request_t *r) 114 | { 115 | ngx_int_t rc; 116 | ngx_http_auth_sqlite_basic_loc_conf_t *alcf; 117 | 118 | /* Sqlite info */ 119 | ngx_int_t sqlite_return_value; 120 | sqlite3_stmt *sqlite_stmt; 121 | sqlite3 *sqlite_handle; 122 | 123 | alcf = ngx_http_get_module_loc_conf(r, ngx_http_auth_sqlite_basic_module); 124 | 125 | if (alcf->realm.len == 0 || alcf->sqlite_db_file.len == 0) { 126 | return NGX_DECLINED; 127 | } 128 | 129 | rc = ngx_http_auth_basic_user(r); 130 | 131 | if (rc == NGX_DECLINED) { 132 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no user/password was provided for basic authentication"); 133 | return ngx_http_auth_sqlite_basic_set_realm(r, &alcf->realm); 134 | } 135 | 136 | if (rc == NGX_ERROR) { 137 | return NGX_HTTP_INTERNAL_SERVER_ERROR; 138 | } 139 | 140 | sqlite_return_value = sqlite3_open((char *) alcf->sqlite_db_file.data, &sqlite_handle); 141 | 142 | if(sqlite_return_value) { 143 | ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, "Opening \"%s\" database failed", alcf->sqlite_db_file.data); 144 | return rc; 145 | } 146 | //FIXME: Dirty work done here as r->headers_in.user.data values is username:password. Following code reads the r->headers_in.user.data upto ":" 147 | ngx_uint_t i = 0; 148 | ngx_str_t login, encoded; // = (char *) malloc(r->headers_in.user.data.len); 149 | 150 | encoded = r->headers_in.authorization->value; 151 | encoded.len -= sizeof("Basic ") - 1; 152 | encoded.data += sizeof("Basic ") - 1; 153 | 154 | login.len = ngx_base64_decoded_length(encoded.len); 155 | login.data = ngx_pnalloc(r->pool, login.len + 1); 156 | 157 | while (r->headers_in.user.data[i] != ':') { 158 | login.data[i] = r->headers_in.user.data[i]; 159 | i++; 160 | } 161 | 162 | login.data[i] = '\0'; 163 | // End // 164 | 165 | 166 | //calculating the length of the required char array 167 | int select_query_len = strlen("select * from ") + 168 | strlen((char *) alcf->sqlite_table.data) + 169 | strlen(" where ") + 170 | strlen((char *) alcf->sqlite_user.data) + 171 | strlen(" = \"") + 172 | strlen((char *) login.data) + 173 | strlen("\" and ") + 174 | strlen((char *) alcf->sqlite_passwd.data) + 175 | strlen(" = \"") + 176 | strlen((char *) r->headers_in.passwd.data) + 177 | strlen("\""); 178 | 179 | //creating array based on calculated length 180 | char select_query[select_query_len + 1]; 181 | sprintf(select_query, "select * from %s where %s = \"%s\" and %s = \"%s\"", (char *) alcf->sqlite_table.data 182 | , (char *) alcf->sqlite_user.data 183 | , (char *) login.data 184 | , (char *) alcf->sqlite_passwd.data 185 | , (char *) r->headers_in.passwd.data); 186 | 187 | const char* tail; 188 | sqlite_return_value = sqlite3_prepare_v2(sqlite_handle, select_query, strlen(select_query), &sqlite_stmt, &tail); 189 | 190 | if (sqlite_return_value != SQLITE_OK) { 191 | ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, "Unable to fetch data from \"%s\" database", alcf->sqlite_db_file.data); 192 | sqlite3_close(sqlite_handle); 193 | return ngx_http_auth_sqlite_basic_set_realm(r, &alcf->realm); 194 | } 195 | 196 | sqlite_return_value = sqlite3_step(sqlite_stmt); 197 | 198 | if(sqlite_return_value == SQLITE_ROW) { 199 | sqlite3_close(sqlite_handle); 200 | return rc; 201 | } 202 | 203 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s was not found in %s table", r->headers_in.user.data, alcf->sqlite_table.data); 204 | 205 | sqlite3_close(sqlite_handle); 206 | 207 | return ngx_http_auth_sqlite_basic_set_realm(r, &alcf->realm); 208 | } 209 | 210 | 211 | static ngx_int_t 212 | ngx_http_auth_sqlite_basic_set_realm(ngx_http_request_t *r, ngx_str_t *realm) 213 | { 214 | r->headers_out.www_authenticate = ngx_list_push(&r->headers_out.headers); 215 | if (r->headers_out.www_authenticate == NULL) { 216 | return NGX_HTTP_INTERNAL_SERVER_ERROR; 217 | } 218 | 219 | r->headers_out.www_authenticate->hash = 1; 220 | ngx_str_set(&r->headers_out.www_authenticate->key, "WWW-Authenticate"); 221 | r->headers_out.www_authenticate->value = *realm; 222 | 223 | return NGX_HTTP_UNAUTHORIZED; 224 | } 225 | 226 | 227 | static void * 228 | ngx_http_auth_sqlite_basic_create_loc_conf(ngx_conf_t *cf) 229 | { 230 | ngx_http_auth_sqlite_basic_loc_conf_t *conf; 231 | 232 | conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_auth_sqlite_basic_loc_conf_t)); 233 | if (conf == NULL) { 234 | return NULL; 235 | } 236 | 237 | return conf; 238 | } 239 | 240 | 241 | static char * 242 | ngx_http_auth_sqlite_basic_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) 243 | { 244 | ngx_http_auth_sqlite_basic_loc_conf_t *prev = parent; 245 | ngx_http_auth_sqlite_basic_loc_conf_t *conf = child; 246 | 247 | if (conf->realm.data == NULL) { 248 | conf->realm = prev->realm; 249 | } 250 | 251 | if (conf->sqlite_db_file.len == 0) { 252 | conf->sqlite_db_file = prev->sqlite_db_file; 253 | } 254 | 255 | return NGX_CONF_OK; 256 | } 257 | 258 | 259 | static ngx_int_t 260 | ngx_http_auth_sqlite_basic_init(ngx_conf_t *cf) 261 | { 262 | ngx_http_handler_pt *h; 263 | ngx_http_core_main_conf_t *cmcf; 264 | 265 | cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); 266 | 267 | h = ngx_array_push(&cmcf->phases[NGX_HTTP_ACCESS_PHASE].handlers); 268 | if (h == NULL) { 269 | return NGX_ERROR; 270 | } 271 | 272 | *h = ngx_http_auth_sqlite_basic_handler; 273 | 274 | return NGX_OK; 275 | } 276 | 277 | 278 | static char * 279 | ngx_http_auth_sqlite_basic(ngx_conf_t *cf, void *post, void *data) 280 | { 281 | ngx_str_t *realm = data; 282 | 283 | size_t len; 284 | u_char *basic, *p; 285 | 286 | if (ngx_strcmp(realm->data, "off") == 0) { 287 | ngx_str_set(realm, ""); 288 | return NGX_CONF_OK; 289 | } 290 | 291 | len = sizeof("Basic realm=\"") - 1 + realm->len + 1; 292 | 293 | basic = ngx_pnalloc(cf->pool, len); 294 | if (basic == NULL) { 295 | return NGX_CONF_ERROR; 296 | } 297 | 298 | p = ngx_cpymem(basic, "Basic realm=\"", sizeof("Basic realm=\"") - 1); 299 | p = ngx_cpymem(p, realm->data, realm->len); 300 | *p = '"'; 301 | 302 | realm->len = len; 303 | realm->data = basic; 304 | 305 | return NGX_CONF_OK; 306 | } 307 | --------------------------------------------------------------------------------