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 1 34 35 36int get_ntlm_type(buffer *msg) 37{ 38 return msg->ptr[8]; 39} 40 41int ntlm_negotiate_response_handler(struct cli_state *cli, char *out) //, char *challenge, int challengeLen) 42{ 43 uint32 olen = 0; 44 unsigned char *tmp; 45 unsigned char blob[512]; 46 int blobLen = smbc_cli_get_smb_secblob(cli, blob); 47 48 int proto = smbc_cli_get_protocol(cli); 49 if (proto >= PROTOCOL_NT1) { 50 //tmp = base64_encode(blob, blobLen, &olen); 51 tmp = ldb_base64_encode(blob, blobLen); 52 olen = strlen(tmp); 53 memcpy(out, tmp, olen); 54 free(tmp); 55 } else if (proto >= PROTOCOL_LANMAN1) { 56 57 } else { 58 59 } 60 61 return olen; 62} 63 64int smb_backend_get_secblob(struct cli_state *cli, uint8_t *blob) 65{ 66 return smbc_cli_get_smb_secblob(cli, blob); 67} 68 69int smb_backend_get_challenge(struct cli_state *cli, char *out) 70{ 71 int prot = smbc_cli_get_protocol(cli); 72 73 if(!out) 74 return -1; 75 76 char blob[512] = {0}; 77 unsigned char *tmp; 78 79 char z = 0; 80 char msg1[] = 81 {(uint8_t)'N', (uint8_t)'T', (uint8_t)'L', (uint8_t)'M', (uint8_t)'S',(uint8_t)'S', (uint8_t)'P', z,(uint8_t)2, z, 82 z, z, z, z, z, z, (uint8_t)40, z, z, z, 83 (uint8_t)1, (uint8_t)130, z, z, z, (uint8_t)2, (uint8_t)2, (uint8_t)2, z, z, 84 z, z, z, z, z, z, z, z, z, z}; 85 86 int len, olen; 87 if (prot >= PROTOCOL_NT1) { 88 len = smbc_cli_get_smb_challenge(cli, blob); 89 memcpy(&msg1[24], blob, 8); 90 tmp = ldb_base64_encode(msg1, 40); 91 olen = strlen(tmp); 92 memcpy(out, tmp, olen); 93 free(tmp); 94 return olen; 95 } else if (prot >= PROTOCOL_LANMAN1) { 96 len = smbc_cli_get_smb_challenge(cli, blob); 97 tmp = ldb_base64_encode(blob, len); 98 olen = strlen(tmp); 99 memcpy(out, tmp, olen); 100 free(tmp); 101 return olen; 102 } else { 103 return 0; 104 } 105 return 0; 106} 107 108int smb_backend_send_negprot(struct cli_state *cli, char *host) 109{ 110 UNUSED(host); 111 if(smbc_cli_send_negprot(cli)) 112 return -1; 113 return 0; 114} 115 116int smb_backend_send_negprot_done(struct cli_state *cli) 117{ 118 if(smbc_cli_send_negprot_done(cli)) 119 return -1; 120 return 0; 121} 122 123int smb_backend_get_protocol(struct cli_state *cli) 124{ 125 return smbc_cli_get_protocol(cli); 126} 127 128int smb_backend_send_session_setup_nego(struct cli_state *cli, 129 void *ntlmssp_state, char *ntlm_msg, int ntlm_len) 130{ 131 if(smbc_cli_send_session_setup_nego(cli, ntlmssp_state, ntlm_msg, ntlm_len)) 132 return -1; 133 return 0; 134} 135 136uint32 smb_backend_send_session_setup_auth(struct cli_state *cli, 137 void *ntlmssp_state, char *ntlm_msg, int ntlm_len) 138{ 139 return smbc_cli_session_setup_ntlmssp_auth(cli, ntlmssp_state, ntlm_msg, ntlm_len); 140} 141 142handler_t ntlm_authentication_handler(server *srv, connection *con, plugin_data *p) 143{ 144 //ntlm_handler_ctx *hctx; 145 data_string *ds_auth; 146 147 //hctx = con->plugin_ctx[p->id]; 148 ds_auth = (data_string *)array_get_element(con->request.headers, "Authorization"); 149 150 Cdbg(DBE, "enter ntlm_authentication_handler..."); 151 Cdbg(DBE, "con->smb_info->state=[%d]", con->smb_info->state); 152 Cdbg(DBE, "con->smb_info->qflag=[%d]", con->smb_info->qflag); 153 Cdbg(DBE, "con->smb_info->cli=[%p]", con->smb_info->cli); 154 155 if(con->smb_info->state == NTLMSSP_DONE) { 156 Cdbg(DBE, "con->smb_info->state == NTLMSSP_DONE"); 157 //re-authentication?? 158#ifdef SUPPORT_REAUTH 159 if (ds_auth != NULL) { 160 NTLM_MESSAGE_TYPE state; 161 char *http_authorization = NULL; 162 http_authorization = ds_auth->value->ptr; 163 Cdbg(DBE, "con->smb_info->state == NTLMSSP_DONE-->re-authentication"); 164 if(strncmp(http_authorization, "NTLM ", 5) == 0) { 165 buffer *ntlm_msg = buffer_init(); 166 if (!base64_decode(ntlm_msg, &http_authorization[5])) { 167 log_error_write(srv, __FILE__, __LINE__, "sb", "decodeing base64-string failed", ntlm_msg); 168 buffer_free(ntlm_msg); 169 return HANDLER_GO_ON; 170 } 171 state = get_ntlm_type(ntlm_msg); 172 173 if(state == NTLMSSP_NEGOTIATE) { 174 int challLen, olen; 175 char out[512]={0}, challenge[512]={0}; 176 smb_connection_free(srv, con, p, con->smb_info); 177 ntlm_handler_ctx_free(hctx); 178 hctx = ntlm_handler_ctx_init(srv, con, p); 179 con->plugin_ctx[p->id] = hctx; 180 con->smb_info->state = state; 181 int res = smb_backend_send_negprot(con->smb_info->cli, con->smb_info->server->ptr); 182 res = smb_backend_send_negprot_done(con->smb_info->cli); 183 int proto = smb_backend_get_protocol(con->smb_info->cli); 184 if(proto >= PROTOCOL_NT1) { 185 uint32_t caps = smbc_cli_get_capabilities(con->smb_info->cli); 186 //fprintf(stderr, "\tRE-AUTH, caps=[%08X]\n", caps); 187 if(caps & CAP_EXTENDED_SECURITY) { 188 con->smb_info->ntlmssp_state = smbc_cli_ntlmssp_state_alloc(); 189 res = smb_backend_send_session_setup_nego(con->smb_info->cli, con->smb_info->ntlmssp_state, ntlm_msg->ptr, ntlm_msg->used); 190 buffer_free(ntlm_msg); 191 olen = ntlm_negotiate_response_handler(con->smb_info->cli, out); 192 //sprintf(challenge, "NTLM %s", out); 193 } else { 194 olen = smb_backend_get_challenge(con->smb_info->cli, out); 195 //sprintf(challenge, "NTLM %s", out); 196 } 197 } else { 198 olen = smb_backend_get_challenge(con->smb_info->cli, out); 199 //sprintf(challenge, "NTLM %s", out); 200 } 201 Cdbg(DBE, "\tRE-AUTH, challenge=[%s]", challenge); 202 buffer_copy_string(p->tmp_buf, challenge); 203 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf)); 204 con->http_status = 401; 205 return HANDLER_FINISHED; 206 } 207 } 208 } 209#endif 210 211 //had authenticated. 212 } 213 else if(con->smb_info->qflag == SMB_HOST_QUERY) { 214 //host_query do the BASIC authentication 215 Cdbg(DBE, "host_query do the BASIC authentication"); 216 } 217 else { 218 if (ds_auth == NULL) { 219 Cdbg(DBE, "ds_auth == NULL"); 220 //send out 401 unauthorized 221 //ntlm_response_401(srv, con, p); 222 smbc_wrapper_response_401(srv, con); 223 con->smb_info->state = NTLMSSP_UNKNOWN; 224 Cdbg(DBE, "\t2 set state to [%d]", con->smb_info->state); 225 return HANDLER_FINISHED; 226 } 227 else if (con->smb_info->state == NTLMSSP_UNKNOWN) { 228 Cdbg(DBE, "con->smb_info->state == NTLMSSP_UNKNOWN"); 229 //send out 401 unauthorized 230 //ntlm_response_401(srv, con, p); 231 smbc_wrapper_response_401(srv, con); 232 con->smb_info->state = NTLMSSP_NEGOTIATE; 233 Cdbg(DBE, "\t3 set state to [%d]", con->smb_info->state); 234 return HANDLER_FINISHED; 235 } 236 else { 237 char *http_authorization = NULL; 238 http_authorization = ds_auth->value->ptr; 239 if(strncmp(http_authorization, "NTLM ", 5) == 0) { 240 buffer *ntlm_msg = buffer_init(); 241 if (!base64_decode(ntlm_msg, &http_authorization[5])) { 242 log_error_write(srv, __FILE__, __LINE__, "sb", "decodeing base64-string failed", ntlm_msg); 243 buffer_free(ntlm_msg); 244 return HANDLER_GO_ON; 245 } 246 247 Cdbg(DBE, "\tntlm_msg = [%s]", ntlm_msg->ptr); 248 con->smb_info->state = get_ntlm_type(ntlm_msg); 249 Cdbg(DBE, "\tstate=[%d]", con->smb_info->state); 250 251 switch(con->smb_info->state) { 252 case NTLMSSP_NEGOTIATE: { //NTLMSSP_NEGOTIATE 253 int challLen, olen; 254 char out[512]={0}, challenge[512]={0}; 255 if(smbc_cli_get_socket(con->smb_info->cli) < 0) { 256#ifdef TODO 257 smb_connection_free(srv, con, p, con->smb_info); 258 ntlm_handler_ctx_free(hctx); 259 hctx = ntlm_handler_ctx_init(srv, con, p); 260 con->plugin_ctx[p->id] = hctx; 261#endif 262 } 263 int res = smb_backend_send_negprot(con->smb_info->cli, con->smb_info->server->ptr); 264 res = smb_backend_send_negprot_done(con->smb_info->cli); 265 int proto = smb_backend_get_protocol(con->smb_info->cli); 266 Cdbg(DBE, "\tNEGO, proto=[%d], res=[%d]", proto, res); 267 268 if(proto >= PROTOCOL_NT1) { 269 uint32_t caps = smbc_cli_get_capabilities(con->smb_info->cli); 270 Cdbg(DBE, "\tNEGO, caps=[%08X]", caps); 271 272 if(caps & CAP_EXTENDED_SECURITY) { 273 con->smb_info->ntlmssp_state = smbc_cli_ntlmssp_state_alloc(); 274 res = smb_backend_send_session_setup_nego(con->smb_info->cli, con->smb_info->ntlmssp_state, ntlm_msg->ptr, ntlm_msg->used); 275 buffer_free(ntlm_msg); 276 olen = ntlm_negotiate_response_handler(con->smb_info->cli, out); 277 sprintf(challenge, "NTLM %s", out); 278 } else { 279 olen = smb_backend_get_challenge(con->smb_info->cli, out); 280 sprintf(challenge, "NTLM %s", out); 281 } 282 } 283 else { 284 olen = smb_backend_get_challenge(con->smb_info->cli, out); 285 sprintf(challenge, "NTLM %s", out); 286 } 287 288 Cdbg(DBE, "\tchallenge=[%s]", challenge); 289 buffer_copy_string(p->tmp_buf, challenge); 290 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf)); 291 con->http_status = 401; 292 return HANDLER_FINISHED; 293 } 294 case NTLMSSP_AUTH: { //NTLMSSP_AUTH 295 uint32 res = 0; 296 int proto = smb_backend_get_protocol(con->smb_info->cli); 297 Cdbg(DBE, "AUTH, proto=[%d]", proto); 298 299 if(proto >= PROTOCOL_NT1) { 300 uint32_t caps = smbc_cli_get_capabilities(con->smb_info->cli); 301 Cdbg(DBE, "AUTH, caps=[%08X]", caps); 302 if(caps & CAP_EXTENDED_SECURITY) { 303 //copy the secblob from http to smb 304 Cdbg(DBE, "copy the secblob from http to smb"); 305 res = smb_backend_send_session_setup_auth(con->smb_info->cli, con->smb_info->ntlmssp_state, ntlm_msg->ptr, ntlm_msg->used); 306 Cdbg(DBE, "copy the secblob from http to smb, res=[%d][%x]", res, res); 307 buffer_free(ntlm_msg); 308 smbc_cli_ntlmssp_state_free(con->smb_info->ntlmssp_state); 309 con->smb_info->ntlmssp_state = NULL; 310 } else { 311 res = smbc_cli_session_setup_lanman2(con->smb_info->cli, ntlm_msg->ptr, ntlm_msg->used); 312 buffer_free(ntlm_msg); 313 } 314 } 315 else { 316 res = smbc_cli_session_setup_lanman2(con->smb_info->cli, ntlm_msg->ptr, ntlm_msg->used); 317 buffer_free(ntlm_msg); 318 } 319 320 if(res) { 321 //authenticate fail, request another authentication 322 char str[5]; 323 sprintf(str, "NTLM"); 324 buffer_copy_string(p->tmp_buf, str); 325 con->smb_info->state = NTLMSSP_UNKNOWN; 326 Cdbg(DBE, "\tauthenticate fail, request another authentication set state to [%d]", con->smb_info->state); 327 response_header_insert(srv, con, CONST_STR_LEN("WWW-Authenticate"), CONST_BUF_LEN(p->tmp_buf)); 328 con->http_status = 401; 329 return HANDLER_FINISHED; 330 } 331 332 con->smb_info->state = NTLMSSP_DONE; 333 //Cdbg(DBE, "\t5 set state to [%d]\n", con->smb_info->state); 334 break; 335 } 336 default: 337 break; 338 } 339 } else { 340 con->http_status = 404; 341 return HANDLER_FINISHED; 342 } 343 } 344 } 345 346 Cdbg(DBE, "1leave ntlm_authentication_handler, con->smb_info->qflag=[%d]", con->smb_info->qflag); 347 if(con->smb_info->state == NTLMSSP_DONE) { 348 //unsigned int res; 349 int res; 350 char turi[256]; 351 switch(con->smb_info->qflag) { 352 case SMB_HOST_QUERY: 353 break; 354 case SMB_SHARE_QUERY: 355 sprintf(turi, "%s/IPC$", con->physical_auth_url->ptr); 356 res = smbc_cli_tree_connect(con->smb_info->cli, turi); 357 break; 358 case SMB_FILE_QUERY: 359 default: 360 { 361 res = smbc_cli_tree_connect(con->smb_info->cli, con->physical_auth_url->ptr); 362 Cdbg(DBE, "leave smbc_cli_tree_connect res=[%X]\n", res); 363 break; 364 } 365 } 366 if( res == NT_STATUS_V(NT_STATUS_LOGON_FAILURE) || 367 res == NT_STATUS_V(NT_STATUS_ACCESS_DENIED) ) 368 { 369 //ntlm_response_401(srv, con, p); 370 smbc_wrapper_response_401(srv, con); 371 con->smb_info->state = NTLMSSP_INITIAL; 372 return HANDLER_FINISHED; 373 } 374 else if(res == 0xc000023a){ 375 Cdbg(DBE, "NT_STATUS_INVALID_CONNECTION\n"); 376 //ntlm_response_401(srv, con, p); 377 smbc_wrapper_response_401(srv, con); 378 con->smb_info->state = NTLMSSP_UNKNOWN; 379 return HANDLER_FINISHED; 380 } 381 382 } 383 384 Cdbg(DBE, "leave ntlm_authentication_handler"); 385 386 return HANDLER_UNSET; 387} 388 389