1#include "base.h" 2#include "log.h" 3#include "buffer.h" 4#include "response.h" 5 6#include "plugin.h" 7 8#include "stream.h" 9#include "stat_cache.h" 10 11#include "sys-mmap.h" 12//////////////////////////////// 13 14#include <sys/types.h> 15#include <sys/stat.h> 16#include <ctype.h> 17#include <stdlib.h> 18#include <string.h> 19#include <errno.h> 20#include <fcntl.h> 21#include <stdio.h> 22#include <assert.h> 23#include <pthread.h> 24#include <signal.h> 25#include <sys/time.h> 26 27#include <unistd.h> 28#include <dirent.h> 29#include <libsmbclient.h> 30#include <dlinklist.h> 31#include "mod_smbdav.h" 32 33#define DBE 0 34 35#ifndef EMBEDDED_EANBLE 36char* g_is_webdav_block = "0"; 37#endif 38 39#if defined(HAVE_LIBXML_H) && defined(HAVE_SQLITE3_H) 40#include <sqlite3.h> 41#endif 42 43int do_account_authentication(const char *username, const char *password){ 44 45 char *nvram_acc_list; 46 47#if EMBEDDED_EANBLE 48 char *a = nvram_get_acc_list(); 49 if(a==NULL) return -1; 50 int l = strlen(a); 51 nvram_acc_list = (char*)malloc(l+1); 52 strncpy(nvram_acc_list, a, l); 53 nvram_acc_list[l] = '\0'; 54 #ifdef APP_IPKG 55 free(a); 56 #endif 57#else 58 int i = 100; 59 nvram_acc_list = (char*)malloc(100); 60 strcpy(nvram_acc_list, "admin>admin<jerry>jerry"); 61#endif 62 63 int account_right = -1; 64 65 char * pch; 66 pch = strtok(nvram_acc_list, "<>"); 67 68 buffer* buffer_acc_name = buffer_init(); 69 buffer* buffer_acc_pass = buffer_init(); 70 71 while(pch!=NULL){ 72 char *name; 73 char *pass; 74 int len; 75 76 //- User Name 77 len = strlen(pch); 78 name = (char*)malloc(len+1); 79 strncpy(name, pch, len); 80 name[len] = '\0'; 81 buffer_copy_string(buffer_acc_name, name); 82 buffer_urldecode_path(buffer_acc_name); 83 free(name); 84 85 //- User Password 86 pch = strtok(NULL,"<>"); 87 len = strlen(pch); 88 pass = (char*)malloc(len+1); 89 strncpy(pass, pch, len); 90 pass[len] = '\0'; 91 buffer_copy_string(buffer_acc_pass, pass); 92 buffer_urldecode_path(buffer_acc_pass); 93 free(pass); 94 95 if( buffer_is_equal_string(buffer_acc_name, username, strlen(username)) && 96 buffer_is_equal_string(buffer_acc_pass, password, strlen(password)) ){ 97 98 //- pass 99 account_right = 1; 100 101 break; 102 } 103 104 pch = strtok(NULL,"<>"); 105 } 106 107 buffer_free(buffer_acc_name); 108 buffer_free(buffer_acc_pass); 109 free(nvram_acc_list); 110 111 aicloud_acc_info_t* c = NULL; 112 for (c = aicloud_acc_info_list; c; c = c->next) { 113 if( buffer_is_equal_string(c->username, username, strlen(username)) && 114 buffer_is_equal_string(c->password, password, strlen(password)) ){ 115 116 //- pass 117 account_right = 1; 118 119 break; 120 } 121 } 122 123 #if 0 124 int jffs_supported = is_jffs_supported(); 125 if(jffs_supported==1){ 126 127 char *err; 128 char sql_query[2048] = "\0"; 129 sqlite3 *sql_aicloud; 130 char **result; 131 int rows; 132 int column_count; 133 char* aicloud_db_file_path = get_aicloud_db_file_path(); 134 135 if (SQLITE_OK == sqlite3_open(aicloud_db_file_path, &(sql_aicloud))) { 136 //- check if account is existed. 137 sprintf(sql_query, "SELECT COUNT(*) AS count FROM account_info WHERE username='%s' AND password='%s'", username, password); 138 if( sql_get_table(sql_aicloud, sql_query, &result, &rows, NULL) == SQLITE_OK ){ 139 Cdbg(DBE, "sql_query=%s, rows=%d", sql_query, rows); 140 141 int count = 0; 142 int i=0; 143 column_count = 1; 144 145 for( i=column_count; i<=rows*column_count; i+=column_count ){ 146 count = atoi(result[i]); 147 } 148 149 sqlite3_free_table(result); 150 151 if(count==1){ 152 //- pass 153 account_right = 1; 154 } 155 } 156 157 if (sql_aicloud) { 158 sqlite3_close(sql_aicloud); 159 } 160 } 161 } 162 #endif 163 164 return account_right; 165} 166 167handler_t basic_authentication_handler(server *srv, connection *con, plugin_data *p) 168{ 169 data_string *ds_auth = (data_string *)array_get_element(con->request.headers, "Authorization"); 170 data_string *ds_useragent = (data_string *)array_get_element(con->request.headers, "user-Agent"); 171 172 buffer *user = buffer_init(); 173 buffer *pass = buffer_init(); 174 buffer_copy_string(user, " "); 175 buffer_copy_string(pass, " "); 176 177 int get_account_from_smb_info = 0; 178 char *auth_username = NULL; 179 char *auth_password = NULL; 180 if( smbc_parser_basic_authentication(srv, con, &auth_username, &auth_password) != 1 ){ 181 182 if(con->smb_info==NULL) 183 goto error_401; 184 185 if( con->smb_info->username->used && con->smb_info->password->used ){ 186 buffer_copy_buffer(user, con->smb_info->username); 187 buffer_copy_buffer(pass, con->smb_info->password); 188 get_account_from_smb_info = 1; 189 } 190 191 Cdbg(DBE, "fail smbc_parser_basic_authentication and get account from smb_info %s, %s", user->ptr, pass->ptr); 192 } 193 else{ 194 buffer_copy_string(user, auth_username); 195 buffer_copy_string(pass, auth_password); 196 free(auth_username); 197 free(auth_password); 198 } 199 200 time_t cur_time = time(NULL); 201 202 double result = difftime(cur_time, con->smb_info->auth_time); 203 204 if(con->smb_info->qflag == SMB_HOST_QUERY) { 205 //data_string *ds2 = (data_string *)array_get_element(con->request.headers, "user-Agent"); 206 207 //- MUST login again more than 30 minutes 208 if(result>1800){ 209 goto error_401; 210 } 211 212 if( con->smb_info && buffer_is_equal_string(con->smb_info->username, "RELOGIN", 7) ){ 213 buffer_reset(con->smb_info->username); 214 buffer_reset(con->smb_info->password); 215 goto error_401; 216 } 217 /* 218 if(con->smb_info->username->used && con->smb_info->password->used){ 219 buffer_copy_buffer(user, con->smb_info->username); 220 buffer_copy_buffer(pass, con->smb_info->password); 221 Cdbg(DBE, "SMB_HOST_QUERY-->copy from smb_info user=[%s], pass=[%s]", user->ptr, pass->ptr); 222 } 223 */ 224#if EMBEDDED_EANBLE 225 //char* webav_user = nvram_get_http_username(); 226 //char* webav_pass = nvram_get_http_passwd(); 227 char* enable_webdav_block = nvram_get_enable_webdav_lock(); 228 char* is_webdav_block = nvram_get_webdav_acc_lock(); 229#ifndef APP_IPKG 230 int try_times = atoi(nvram_get_webdav_lock_times()); 231 int try_interval = atoi(nvram_get_webdav_lock_interval())*60; 232#else 233 char* lock_times = nvram_get_webdav_lock_times(); 234 char* lock_interval = nvram_get_webdav_lock_interval(); 235 int try_times = atoi(lock_times); 236 int try_interval = atoi(lock_interval)*60; 237#endif 238#else 239 //char* webav_user = "admin"; 240 //char* webav_pass = "admin"; 241 char* enable_webdav_block = "1"; 242 char* is_webdav_block = g_is_webdav_block; 243 int try_times = 3; 244 int try_interval = 1*60; //- 1 minutes 245#endif 246 int isBrowser = ( ds_useragent && (strstr( ds_useragent->value->ptr, "Mozilla" ) || strstr( ds_useragent->value->ptr, "Opera" ))) ? 1 : 0; 247 if( isBrowser == 1 && strcmp(enable_webdav_block, "1") == 0 && strcmp(is_webdav_block, "1") == 0 ){ 248 Cdbg(DBE, "Direct go to 455 error page"); 249#if EMBEDDED_EANBLE 250#ifdef APP_IPKG 251 //free(webav_user); 252 //free(webav_pass); 253 free(enable_webdav_block); 254 free(is_webdav_block); 255 free(lock_times); 256 free(lock_interval); 257#endif 258#endif 259 goto error_455; 260 } 261 262 if( do_account_authentication(user->ptr, pass->ptr) != 1 ){ 263 //if( smbc_acc_account_authentication(con, user->ptr, pass->ptr) != 1 ){ 264 //if( strcmp(user->ptr, webav_user)!=0 || strcmp(pass->ptr, webav_pass)!=0 ){ 265 266 //- login failed. 267 268 if( isBrowser==1 && strcmp(enable_webdav_block, "1") == 0 && con->smb_info && ds_auth!=NULL ){ 269 //- block user 270 271 con->smb_info->login_count++; 272 273 time_t current_time = time(NULL); 274 275 double result2 = difftime(cur_time, con->smb_info->login_begin_time); 276 if( result2 > try_interval ){ 277 con->smb_info->login_count = 1; 278 } 279 280 if(con->smb_info->login_count==1) 281 con->smb_info->login_begin_time = time(NULL); 282 283 Cdbg(DBE, "con->smb_info->login_count=[%d][%d]", con->smb_info->login_count, try_times); 284 if(con->smb_info->login_count>=try_times){ 285 286 con->smb_info->login_count = 0; 287 288 #if EMBEDDED_EANBLE 289 nvram_set_webdav_acc_lock("1"); 290 nvram_do_commit(); 291 #else 292 g_is_webdav_block = "1"; 293 #endif 294 295 Cdbg(DBE, "error_455..."); 296#if EMBEDDED_EANBLE 297#ifdef APP_IPKG 298 //free(webav_user); 299 //free(webav_pass); 300 free(enable_webdav_block); 301 free(is_webdav_block); 302 free(lock_times); 303 free(lock_interval); 304#endif 305#endif 306 goto error_455; 307 } 308 } 309#if EMBEDDED_EANBLE 310#ifdef APP_IPKG 311 //free(webav_user); 312 //free(webav_pass); 313 free(enable_webdav_block); 314 free(is_webdav_block); 315 free(lock_times); 316 free(lock_interval); 317#endif 318#endif 319 goto error_401; 320 } 321 322 if(con->smb_info){ 323 con->smb_info->login_count = 0; 324 } 325 326 if(!get_account_from_smb_info){ 327 log_sys_write(srv, "ssss", "User", user->ptr, "login from ip", con->dst_addr_buf->ptr); 328 329 buffer_copy_buffer(srv->last_login_info, srv->cur_login_info); 330 331 buffer_copy_string(srv->cur_login_info, user->ptr); 332 buffer_append_string(srv->cur_login_info, ">"); 333 334 char srv_time[255]; 335 strftime(srv_time, 254, "%Y/%m/%d %H:%M:%S", localtime(&(srv->cur_ts))); 336 buffer_append_string(srv->cur_login_info, srv_time); 337 buffer_append_string(srv->cur_login_info, ">"); 338 339 buffer_append_string(srv->cur_login_info, con->dst_addr_buf->ptr); 340 341 #if EMBEDDED_EANBLE 342 nvram_set_webdav_last_login_info(srv->last_login_info->ptr); 343 #endif 344 } 345#if EMBEDDED_EANBLE 346#ifdef APP_IPKG 347 //free(webav_user); 348 //free(webav_pass); 349 free(enable_webdav_block); 350 free(is_webdav_block); 351 free(lock_times); 352 free(lock_interval); 353#endif 354#endif 355 } 356 else { 357 358 //- check user / password 359 struct stat st; 360 361 if( con->smb_info && buffer_is_equal_string(con->smb_info->username, "RELOGIN", 7) ){ 362 buffer_reset(con->smb_info->username); 363 buffer_reset(con->smb_info->password); 364 365 goto error_401; 366 } 367 368 int res = smbc_server_check_creds( con->smb_info->server->ptr, 369 con->smb_info->share->ptr, 370 con->smb_info->workgroup->ptr, 371 user->ptr, 372 pass->ptr ); 373 374 //if( res == NT_STATUS_V(NT_STATUS_NOT_SUPPORTED)) { 375 if( res == 0xc00000bb ){ 376 buffer_free(user); 377 buffer_free(pass); 378 con->http_status = 406; 379 380 return HANDLER_FINISHED; 381 } 382 else if(res != 0) { //the username/password for smb_server is not correct 383 if(con->smb_info->username->used && con->smb_info->password->used){ 384 buffer_copy_buffer(user, con->smb_info->username); 385 buffer_copy_buffer(pass, con->smb_info->password); 386 Cdbg(DBE, "Try to login again, server=%s, share=%s, user=%s, pass=%s", 387 con->smb_info->server->ptr, 388 con->smb_info->share->ptr, 389 user->ptr, pass->ptr); 390 391 //- MUST login again more than 30 minutes 392 if(result>1800){ 393 buffer_copy_string(pass, ""); 394 } 395 396 int res = smbc_server_check_creds(con->smb_info->server->ptr, 397 con->smb_info->share->ptr, 398 con->smb_info->workgroup->ptr, 399 user->ptr, 400 pass->ptr); 401 402 if(res != 0) 403 goto error_401; 404 } 405 else 406 goto error_401; 407 } 408 409 if(!get_account_from_smb_info) 410 log_sys_write(srv, "sssbss", "User", user->ptr, "login", con->smb_info->server, "from ip", con->dst_addr_buf->ptr); 411 } 412 413 con->smb_info->auth_time = time(NULL); 414 415 if( !buffer_is_equal_string(user, "no", 2) && !buffer_is_equal_string(pass, "no", 2)){ 416 buffer_copy_buffer(con->smb_info->username, user); 417 buffer_copy_buffer(con->smb_info->password, pass); 418 Cdbg(DBE, "save username=[%s], password=[%s], time=[%d] to con->smb_info", con->smb_info->username->ptr, con->smb_info->password->ptr, con->smb_info->auth_time); 419 } 420 421 buffer_free(user); 422 buffer_free(pass); 423 424 return HANDLER_UNSET; 425 426error_401: 427 buffer_free(user); 428 buffer_free(pass); 429 430 if(con->smb_info) 431 con->smb_info->auth_time = time(NULL); 432 433 smbc_wrapper_response_401(srv, con); 434 435 return HANDLER_FINISHED; 436 437error_455: 438 //- Block webdav 439 buffer_free(user); 440 buffer_free(pass); 441 con->http_status = 455; 442 return HANDLER_FINISHED; 443 444} 445