• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/lighttpd-1.4.39/src/
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