aboutsummaryrefslogtreecommitdiffstats
path: root/smbutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'smbutil.c')
-rw-r--r--smbutil.c219
1 files changed, 219 insertions, 0 deletions
diff --git a/smbutil.c b/smbutil.c
new file mode 100644
index 00000000..cbe18b99
--- /dev/null
+++ b/smbutil.c
@@ -0,0 +1,219 @@
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+#include <string.h>
+#include "ntlm.h"
+#include "smbencrypt.h"
+#include "smbbyteorder.h"
+#include "fetchmail.h"
+
+char versionString[] ="libntlm version 0.21";
+
+/* Utility routines that handle NTLM auth structures. */
+
+/* The [IS]VAL macros are to take care of byte order for non-Intel
+ * Machines -- I think this file is OK, but it hasn't been tested.
+ * The other files (the ones stolen from Samba) should be OK.
+ */
+
+
+/* I am not crazy about these macros -- they seem to have gotten
+ * a bit complex. A new scheme for handling string/buffer fields
+ * in the structures probably needs to be designed
+ */
+
+#define AddBytes(ptr, header, buf, count) \
+{ \
+if (buf && count) \
+ { \
+ SSVAL(&ptr->header.len,0,count); \
+ SSVAL(&ptr->header.maxlen,0,count); \
+ SIVAL(&ptr->header.offset,0,((ptr->buffer - ((uint8*)ptr)) + ptr->bufIndex)); \
+ memcpy(ptr->buffer+ptr->bufIndex, buf, count); \
+ ptr->bufIndex += count; \
+ } \
+else \
+ { \
+ ptr->header.len = \
+ ptr->header.maxlen = 0; \
+ SIVAL(&ptr->header.offset,0,ptr->bufIndex); \
+ } \
+}
+
+#define AddString(ptr, header, string) \
+{ \
+char *p = string; \
+int len = 0; \
+if (p) len = strlen(p); \
+AddBytes(ptr, header, ((unsigned char*)p), len); \
+}
+
+#define AddUnicodeString(ptr, header, string) \
+{ \
+char *p = string; \
+unsigned char *b = NULL; \
+int len = 0; \
+if (p) \
+ { \
+ len = strlen(p); \
+ b = strToUnicode(p); \
+ } \
+AddBytes(ptr, header, b, len*2); \
+}
+
+
+#define GetUnicodeString(structPtr, header) \
+unicodeToString(((char*)structPtr) + IVAL(&structPtr->header.offset,0) , SVAL(&structPtr->header.len,0)/2)
+#define GetString(structPtr, header) \
+toString((((char *)structPtr) + IVAL(&structPtr->header.offset,0)), SVAL(&structPtr->header.len,0))
+#define DumpBuffer(fp, structPtr, header) \
+dumpRaw(fp,((unsigned char*)structPtr)+IVAL(&structPtr->header.offset,0),SVAL(&structPtr->header.len,0))
+
+
+static void dumpRaw(FILE *fp, unsigned char *buf, size_t len)
+ {
+ int i;
+
+ for (i=0; i<len; ++i)
+ fprintf(fp,"%02x ",buf[i]);
+
+ fprintf(fp,"\n");
+ }
+
+static char *unicodeToString(char *p, size_t len)
+ {
+ int i;
+ static char buf[1024];
+
+ assert(len+1 < sizeof buf);
+
+ for (i=0; i<len; ++i)
+ {
+ buf[i] = *p & 0x7f;
+ p += 2;
+ }
+
+ buf[i] = '\0';
+ return buf;
+ }
+
+static unsigned char *strToUnicode(char *p)
+ {
+ static unsigned char buf[1024];
+ size_t l = strlen(p);
+ int i = 0;
+
+ assert(l*2 < sizeof buf);
+
+ while (l--)
+ {
+ buf[i++] = *p++;
+ buf[i++] = 0;
+ }
+
+ return buf;
+ }
+
+static unsigned char *toString(char *p, size_t len)
+ {
+ static unsigned char buf[1024];
+
+ assert(len+1 < sizeof buf);
+
+ memcpy(buf,p,len);
+ buf[len] = 0;
+ return buf;
+ }
+
+void dumpSmbNtlmAuthRequest(FILE *fp, tSmbNtlmAuthRequest *request)
+ {
+ fprintf(fp,"NTLM Request:\n");
+ fprintf(fp," Ident = %s\n",request->ident);
+ fprintf(fp," mType = %d\n",IVAL(&request->msgType,0));
+ fprintf(fp," Flags = %08x\n",IVAL(&request->flags,0));
+ fprintf(fp," User = %s\n",GetString(request,user));
+ fprintf(fp," Domain = %s\n",GetString(request,domain));
+ }
+
+void dumpSmbNtlmAuthChallenge(FILE *fp, tSmbNtlmAuthChallenge *challenge)
+ {
+ fprintf(fp,"NTLM Challenge:\n");
+ fprintf(fp," Ident = %s\n",challenge->ident);
+ fprintf(fp," mType = %d\n",IVAL(&challenge->msgType,0));
+ fprintf(fp," Domain = %s\n",GetUnicodeString(challenge,uDomain));
+ fprintf(fp," Flags = %08x\n",IVAL(&challenge->flags,0));
+ fprintf(fp," Challenge = "); dumpRaw(fp, challenge->challengeData,8);
+ }
+
+void dumpSmbNtlmAuthResponse(FILE *fp, tSmbNtlmAuthResponse *response)
+ {
+ fprintf(fp,"NTLM Response:\n");
+ fprintf(fp," Ident = %s\n",response->ident);
+ fprintf(fp," mType = %d\n",IVAL(&response->msgType,0));
+ fprintf(fp," LmResp = "); DumpBuffer(fp,response,lmResponse);
+ fprintf(fp," NTResp = "); DumpBuffer(fp,response,ntResponse);
+ fprintf(fp," Domain = %s\n",GetUnicodeString(response,uDomain));
+ fprintf(fp," User = %s\n",GetUnicodeString(response,uUser));
+ fprintf(fp," Wks = %s\n",GetUnicodeString(response,uWks));
+ fprintf(fp," sKey = "); DumpBuffer(fp, response,sessionKey);
+ fprintf(fp," Flags = %08x\n",IVAL(&response->flags,0));
+ }
+
+void buildSmbNtlmAuthRequest(tSmbNtlmAuthRequest *request, char *user, char *domain)
+ {
+ char *u = xstrdup(user);
+ char *p = strchr(u,'@');
+
+ if (p)
+ {
+ if (!domain)
+ domain = p+1;
+ *p = '\0';
+ }
+
+ request->bufIndex = 0;
+ memcpy(request->ident,"NTLMSSP\0\0\0",8);
+ SIVAL(&request->msgType,0,1);
+ SIVAL(&request->flags,0,0x0000b207); /* have to figure out what these mean */
+ AddString(request,user,u);
+ AddString(request,domain,domain);
+ free(u);
+ }
+
+void buildSmbNtlmAuthResponse(tSmbNtlmAuthChallenge *challenge, tSmbNtlmAuthResponse *response, char *user, char *password)
+ {
+ uint8 lmRespData[24];
+ uint8 ntRespData[24];
+ char *d = xstrdup(GetUnicodeString(challenge,uDomain));
+ char *domain = d;
+ char *u = xstrdup(user);
+ char *p = strchr(u,'@');
+
+ if (p)
+ {
+ domain = p+1;
+ *p = '\0';
+ }
+
+ SMBencrypt(password, challenge->challengeData, lmRespData);
+ SMBNTencrypt(password, challenge->challengeData, ntRespData);
+
+ response->bufIndex = 0;
+ memcpy(response->ident,"NTLMSSP\0\0\0",8);
+ SIVAL(&response->msgType,0,3);
+
+ AddBytes(response,lmResponse,lmRespData,24);
+ AddBytes(response,ntResponse,ntRespData,24);
+ AddUnicodeString(response,uDomain,domain);
+ AddUnicodeString(response,uUser,u);
+ AddUnicodeString(response,uWks,u);
+ AddString(response,sessionKey,NULL);
+
+ response->flags = challenge->flags;
+
+ free(d);
+ free(u);
+ }
+