}
+/* a helpful macro to avoid running over the end of our blob */
+#define NEED_DATA(amount) \
+if (head_ofs + amount > blob->length) { \
+ return False; \
+}
+
/*
this is a tiny msrpc packet parser. This the the partner of msrpc_gen
d = word (4 bytes)
C = constant ascii string
*/
+
BOOL msrpc_parse(DATA_BLOB *blob,
const char *format, ...)
{
for (i=0; format[i]; i++) {
switch (format[i]) {
case 'U':
+ NEED_DATA(8);
len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
ptr = IVAL(blob->data, head_ofs); head_ofs += 4;
+
/* make sure its in the right format - be strict */
- if (len1 != len2 || (len1&1) || ptr + len1 > blob->length) {
+ if (len1 != len2 || ptr + len1 > blob->length) {
+ return False;
+ }
+ if (len1 & 1) {
+ /* if odd length and unicode */
return False;
}
+
ps = va_arg(ap, char **);
- pull_string(NULL, p, blob->data + ptr, -1, len1,
- STR_UNICODE|STR_NOALIGN);
- (*ps) = strdup(p);
+ if (0 < len1) {
+ pull_string(NULL, p, blob->data + ptr, sizeof(p),
+ len1,
+ STR_UNICODE|STR_NOALIGN);
+ (*ps) = strdup(p);
+ } else {
+ (*ps) = NULL;
+ }
break;
case 'A':
+ NEED_DATA(8);
len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
ptr = IVAL(blob->data, head_ofs); head_ofs += 4;
if (len1 != len2 || ptr + len1 > blob->length) {
return False;
}
+
ps = va_arg(ap, char **);
if (0 < len1) {
- pull_string(NULL, p, blob->data + ptr, -1,
- len1, STR_ASCII|STR_NOALIGN);
+ pull_string(NULL, p, blob->data + ptr, sizeof(p),
+ len1,
+ STR_ASCII|STR_NOALIGN);
(*ps) = strdup(p);
} else {
(*ps) = NULL;
}
break;
case 'B':
+ NEED_DATA(8);
len1 = SVAL(blob->data, head_ofs); head_ofs += 2;
len2 = SVAL(blob->data, head_ofs); head_ofs += 2;
ptr = IVAL(blob->data, head_ofs); head_ofs += 4;
case 'b':
b = (DATA_BLOB *)va_arg(ap, void *);
len1 = va_arg(ap, unsigned);
- *b = data_blob(blob->data + head_ofs,
- MIN(len1, blob->length - head_ofs));
+ /* make sure its in the right format - be strict */
+ NEED_DATA(len1);
+ *b = data_blob(blob->data + head_ofs, len1);
head_ofs += len1;
break;
case 'd':
v = va_arg(ap, uint32 *);
+ NEED_DATA(4);
*v = IVAL(blob->data, head_ofs); head_ofs += 4;
break;
case 'C':
&neg_flags,
&cliname,
&domname)) {
- return NT_STATUS_LOGON_FAILURE;
+ return NT_STATUS_INVALID_PARAMETER;
}
SAFE_FREE(cliname);
data_blob_free(&struct_blob);
+ ntlmssp_state->expected_state = NTLMSSP_AUTH;
+
return NT_STATUS_MORE_PROCESSING_REQUIRED;
}
&ntlmssp_state->workstation,
&sess_key,
&neg_flags)) {
- return NT_STATUS_LOGON_FAILURE;
+ return NT_STATUS_INVALID_PARAMETER;
}
data_blob_free(&sess_key);
*ntlmssp_state = talloc_zero(mem_ctx, sizeof(**ntlmssp_state));
if (!*ntlmssp_state) {
- DEBUG(0,("ntlmssp_start: talloc failed!\n"));
+ DEBUG(0,("ntlmssp_server_start: talloc failed!\n"));
talloc_destroy(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
(*ntlmssp_state)->get_domain = lp_workgroup;
(*ntlmssp_state)->server_role = ROLE_DOMAIN_MEMBER; /* a good default */
+ (*ntlmssp_state)->expected_state = NTLMSSP_NEGOTIATE;
+
return NT_STATUS_OK;
}
if (!msrpc_parse(&request, "Cd",
"NTLMSSP",
&ntlmssp_command)) {
-
- return NT_STATUS_LOGON_FAILURE;
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (ntlmssp_command != ntlmssp_state->expected_state) {
+ return NT_STATUS_INVALID_PARAMETER;
}
if (ntlmssp_command == NTLMSSP_NEGOTIATE) {
} else if (ntlmssp_command == NTLMSSP_AUTH) {
return ntlmssp_server_auth(ntlmssp_state, request, reply);
} else {
- return NT_STATUS_LOGON_FAILURE;
+ return NT_STATUS_INVALID_PARAMETER;
}
}