summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/negprot.c95
1 files changed, 66 insertions, 29 deletions
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 4a9492a766..4e3d8f1b3e 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -481,16 +481,17 @@ static const struct {
****************************************************************************/
int reply_negprot(connection_struct *conn,
- char *inbuf,char *outbuf, int dum_size,
+ char *inbuf,char *outbuf, int size,
int dum_buffsize)
{
int outsize = set_message(inbuf,outbuf,1,0,True);
- int Index=0;
int choice= -1;
int protocol;
char *p;
- int bcc = SVAL(smb_buf(inbuf),-2);
int arch = ARCH_ALL;
+ int num_cliprotos;
+ char **cliprotos;
+ int i;
static BOOL done_negprot = False;
@@ -502,41 +503,78 @@ int reply_negprot(connection_struct *conn,
}
done_negprot = True;
+ if (inbuf[size-1] != '\0') {
+ DEBUG(0, ("negprot protocols not 0-terminated\n"));
+ END_PROFILE(SMBnegprot);
+ return ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ }
+
p = smb_buf(inbuf)+1;
- while (p < (smb_buf(inbuf) + bcc)) {
- Index++;
- DEBUG(3,("Requested protocol [%s]\n",p));
- if (strcsequal(p,"Windows for Workgroups 3.1a"))
- arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
- else if (strcsequal(p,"DOS LM1.2X002"))
+
+ num_cliprotos = 0;
+ cliprotos = NULL;
+
+ while (smb_bufrem(inbuf, p) > 0) {
+ char **tmp;
+
+ tmp = TALLOC_REALLOC_ARRAY(tmp_talloc_ctx(), cliprotos, char *,
+ num_cliprotos+1);
+ if (tmp == NULL) {
+ DEBUG(0, ("talloc failed\n"));
+ TALLOC_FREE(cliprotos);
+ END_PROFILE(SMBnegprot);
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ cliprotos = tmp;
+
+ if (pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p)
+ == (size_t)-1) {
+ DEBUG(0, ("pull_ascii_talloc failed\n"));
+ TALLOC_FREE(cliprotos);
+ END_PROFILE(SMBnegprot);
+ return ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ DEBUG(3, ("Requested protocol [%s]\n",
+ cliprotos[num_cliprotos]));
+
+ num_cliprotos += 1;
+ p += strlen(p) + 2;
+ }
+
+ for (i=0; i<num_cliprotos; i++) {
+ if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
+ arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
+ | ARCH_WIN2K );
+ else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
arch &= ( ARCH_WFWG | ARCH_WIN95 );
- else if (strcsequal(p,"DOS LANMAN2.1"))
+ else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
arch &= ( ARCH_WFWG | ARCH_WIN95 );
- else if (strcsequal(p,"NT LM 0.12"))
- arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
- else if (strcsequal(p,"SMB 2.001"))
+ else if (strcsequal(cliprotos[i], "NT LM 0.12"))
+ arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
+ | ARCH_CIFSFS);
+ else if (strcsequal(cliprotos[i], "SMB 2.001"))
arch = ARCH_VISTA;
- else if (strcsequal(p,"LANMAN2.1"))
+ else if (strcsequal(cliprotos[i], "LANMAN2.1"))
arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
- else if (strcsequal(p,"LM1.2X002"))
+ else if (strcsequal(cliprotos[i], "LM1.2X002"))
arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
- else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
+ else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
arch &= ARCH_WINNT;
- else if (strcsequal(p,"XENIX CORE"))
+ else if (strcsequal(cliprotos[i], "XENIX CORE"))
arch &= ( ARCH_WINNT | ARCH_OS2 );
- else if (strcsequal(p,"Samba")) {
+ else if (strcsequal(cliprotos[i], "Samba")) {
arch = ARCH_SAMBA;
break;
- } else if (strcsequal(p,"POSIX 2")) {
+ } else if (strcsequal(cliprotos[i], "POSIX 2")) {
arch = ARCH_CIFSFS;
break;
}
-
- p += strlen(p) + 2;
}
/* CIFSFS can send one arch only, NT LM 0.12. */
- if (Index == 1 && (arch & ARCH_CIFSFS)) {
+ if (i == 1 && (arch & ARCH_CIFSFS)) {
arch = ARCH_CIFSFS;
}
@@ -588,15 +626,13 @@ int reply_negprot(connection_struct *conn,
/* Check for protocols, most desirable first */
for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
- p = smb_buf(inbuf)+1;
- Index = 0;
+ i = 0;
if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
(supported_protocols[protocol].protocol_level >= lp_minprotocol()))
- while (p < (smb_buf(inbuf) + bcc)) {
- if (strequal(p,supported_protocols[protocol].proto_name))
- choice = Index;
- Index++;
- p += strlen(p) + 2;
+ while (i < num_cliprotos) {
+ if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
+ choice = i;
+ i++;
}
if(choice != -1)
break;
@@ -620,6 +656,7 @@ int reply_negprot(connection_struct *conn,
"client negotiated a downlevel protocol");
}
+ TALLOC_FREE(cliprotos);
END_PROFILE(SMBnegprot);
return(outsize);
}