summaryrefslogtreecommitdiff
path: root/daemon/ntlmssp.c
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2006-05-10 17:33:18 +0000
committerStef Walter <stef@memberwebs.com>2006-05-10 17:33:18 +0000
commitf5164b1be2a17e2dba5908f08ba270cf035d6546 (patch)
tree85c5d7973851d9f3105e92b900a50a43c12f1a94 /daemon/ntlmssp.c
parente593016a80ceee52b6e3244512ff4307f8c208fa (diff)
Some missing files
Diffstat (limited to 'daemon/ntlmssp.c')
-rw-r--r--daemon/ntlmssp.c444
1 files changed, 444 insertions, 0 deletions
diff --git a/daemon/ntlmssp.c b/daemon/ntlmssp.c
new file mode 100644
index 0000000..ecc5df9
--- /dev/null
+++ b/daemon/ntlmssp.c
@@ -0,0 +1,444 @@
+/*
+ * $Id: ntlmssp.c,v 1.1 2004/04/21 17:37:06 nate Exp $
+ *
+ */
+
+#include <sys/socket.h>
+#include <sys/vfs.h>
+
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include "ntlmssp.h"
+#include "smbval/smblib-priv.h"
+
+/* -----------------------------------------------------------------------------
+ * What new hell is this? From mod_ntlm2
+ */
+
+#include "smbval/byteorder.h"
+#include "smbval/std-defines.h"
+#include "smbval/std-includes.h"
+#include "smbval/smblib-common.h"
+#include "smbval/smblib-priv.h"
+#include "smbval/rfcnb-common.h"
+#include "smbval/rfcnb-error.h"
+#include "smbval/rfcnb-priv.h"
+#include "smbval/rfcnb-util.h"
+#include "smbval/rfcnb-io.h"
+#include "smbval/rfcnb.h"
+
+#include "smbval/rfcnb-io.inc.c"
+#include "smbval/rfcnb-util.inc.c"
+#include "smbval/session.inc.c"
+#include "smbval/smbdes.inc.c"
+#include "smbval/smbencrypt.inc.c"
+#include "smbval/smblib-util.inc.c"
+#include "smbval/smblib.inc.c"
+
+/* -------------------------------------------------------------------------- */
+
+#define little_endian_word(x) x[0] + (((unsigned)x[1]) << 8)
+/* fhz 02-02-09: typecasting is needed for a generic use */
+#define set_little_endian_word(x,y) (*((char *)x))=(y&0xff);*(((char*)x)+1)=((y>>8)&0xff)
+
+static int
+ntlm_msg_type(unsigned char *raw_msg, unsigned msglen)
+{
+ struct ntlm_msg1 *msg = (struct ntlm_msg1 *) raw_msg;
+
+ if (msglen < 9)
+ return -1;
+ if (strncmp((char*)msg->protocol, "NTLMSSP", 8))
+ return -1;
+ return msg->type;
+}
+
+static int
+ntlm_extract_mem(unsigned char *dst,
+ unsigned char *src, unsigned srclen,
+ unsigned char *off, unsigned char *len,
+ unsigned max)
+{
+ unsigned o = little_endian_word(off);
+ unsigned l = little_endian_word(len);
+ if (l > max)
+ return -1;
+ if (o >= srclen)
+ return -1;
+ if (o + l > srclen)
+ return -1;
+ src += o;
+ while (l-- > 0)
+ *dst++ = *src++;
+ return 0;
+}
+
+static int
+ntlm_extract_string(unsigned char *dst,
+ unsigned char *src, unsigned srclen,
+ unsigned char *off, unsigned char *len,
+ unsigned max)
+{
+ unsigned o = little_endian_word(off);
+ unsigned l = little_endian_word(len);
+ if (l > max)
+ return -1;
+ if (o >= srclen)
+ return -1;
+ if (o + l > srclen)
+ return -1;
+ src += o;
+ while (l-- > 0) {
+ /* +csz 2003/02/20 - En algunos casos vienen \0 entremedio */
+ if ( *src != '\0' ) {
+ *dst = *src;
+ dst++;
+ }
+ src++;
+ }
+ *dst = 0;
+ return 0;
+}
+
+static int
+ntlm_put_in_unicode(unsigned char *dst,
+ unsigned char *src, unsigned srclen, unsigned max)
+{
+ unsigned l = srclen*2;
+ if (l > max)
+ l=max; /* fhz: bad very bad */
+ while (l > 0) {
+ /* ASCII to unicode*/
+ *dst++ = *src++;
+ *dst++=0;
+ l -=2;
+ }
+ return 0;
+
+
+
+}
+
+static int
+ntlm_extract_unicode(unsigned char *dst,
+ unsigned char *src, unsigned srclen,
+ unsigned char *off, unsigned char *len,
+ unsigned max)
+{
+ unsigned o = little_endian_word(off);
+ unsigned l = little_endian_word(len) / 2; /* Unicode! */
+ if (l > max)
+ return -1;
+ if (o >= srclen)
+ return -1;
+ if (o + l > srclen)
+ return -1;
+ src += o;
+ while (l > 0) {
+ /* Unicode to ASCII */
+ *dst++ = *src;
+ src += 2;
+ l -= 2;
+ }
+ *dst = 0;
+ return 0;
+}
+
+static int
+ntlm_msg1_getntlmssp_flags(unsigned char *raw_msg,
+ unsigned char *ntlmssp_flags)
+{
+ struct ntlm_msg1 *msg = (struct ntlm_msg1 *) raw_msg;
+ *ntlmssp_flags=little_endian_word(msg->flags);
+ return 0;
+}
+
+static int
+ntlm_msg1_gethostname(unsigned char *raw_msg,
+ unsigned msglen, unsigned char *hostname)
+{
+ struct ntlm_msg1 *msg = (struct ntlm_msg1 *) raw_msg;
+ if (ntlm_extract_string(hostname, (unsigned char*) msg, msglen,
+ msg->host_off, msg->host_len, MAX_HOSTLEN))
+ return 1;
+ return 0;
+}
+
+static int
+ntlm_msg1_getdomainname(unsigned char *raw_msg,
+ unsigned msglen, unsigned char *domainname)
+{
+ struct ntlm_msg1 *msg = (struct ntlm_msg1 *) raw_msg;
+ if (ntlm_extract_string(domainname, (unsigned char*) msg,
+ msglen, msg->dom_off, msg->dom_len, MAX_DOMLEN))
+ return 2;
+ return 0;
+}
+
+static int
+ntlm_msg3_getlm(unsigned char *raw_msg, unsigned msglen,
+ unsigned char *lm)
+{
+ struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
+ if (ntlm_extract_mem(lm, (unsigned char*) msg, msglen, msg->lm_off,
+ msg->lm_len, RESP_LEN))
+ return 4;
+ return 0;
+}
+
+static int
+ntlm_msg3_getnt(unsigned char *raw_msg, unsigned msglen,
+ unsigned char *nt)
+{
+ struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
+ if (ntlm_extract_mem(nt, (unsigned char*) msg, msglen, msg->nt_off,
+ msg->nt_len, RESP_LEN))
+ /* Win9x: we can't extract nt ... so we use lm... */
+ if (ntlm_extract_mem(nt, (unsigned char*) msg, msglen, msg->lm_off,
+ msg->lm_len, RESP_LEN))
+ return 8;
+ return 0;
+}
+
+static int
+ntlm_msg3_getusername(unsigned char *raw_msg,
+ unsigned msglen, unsigned char *username,
+ unsigned ntlmssp_flags)
+{
+ struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
+ int c;
+ if (ntlmssp_flags & NTLMSSP_NEGOTIATE_UNICODE) {
+ if (ntlm_extract_unicode(username, (unsigned char*)msg, msglen,
+ msg->user_off, msg->user_len, MAX_USERLEN))
+ return 16;
+ }
+ else { /* ascii */
+ if (ntlm_extract_string(username, (unsigned char*)msg, msglen,
+ msg->user_off, msg->user_len, MAX_USERLEN))
+ return 16;
+ else {
+ /* Win9x client leave username in uppercase...fix it: */
+ while (*username!=(unsigned char)NULL) {
+ c=tolower((int)*username);
+ *username=(unsigned char)c;
+ username++;
+ }
+ }
+ }
+ return 0;
+}
+
+static int
+ntlm_msg3_gethostname(unsigned char *raw_msg, unsigned msglen,
+ unsigned char *hostname,unsigned ntlmssp_flags)
+{
+ struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
+ if (ntlmssp_flags & NTLMSSP_NEGOTIATE_UNICODE) {
+ if (ntlm_extract_unicode(hostname, (unsigned char*) msg, msglen,
+ msg->host_off, msg->host_len, MAX_HOSTLEN))
+ return 0; /* this one FAILS, but since the value is not used,
+ * we just pretend it was ok. */
+ }
+ else { /* ascii */
+ if (ntlm_extract_string(hostname, (unsigned char*) msg, msglen,
+ msg->host_off, msg->host_len, MAX_HOSTLEN))
+ return 0; /* this one FAILS, but since the value is not used,
+ * we just pretend it was ok. */
+ }
+ return 0;
+}
+
+static int
+ntlm_msg3_getdomainname(unsigned char *raw_msg,
+ unsigned msglen, unsigned char *domainname,
+ unsigned ntlmssp_flags)
+{
+ struct ntlm_msg3 *msg = (struct ntlm_msg3 *) raw_msg;
+ if (ntlmssp_flags & NTLMSSP_NEGOTIATE_UNICODE) {
+ if (ntlm_extract_unicode(domainname, (unsigned char*) msg, msglen,
+ msg->dom_off, msg->dom_len, MAX_DOMLEN))
+ return 64;
+ }
+ else { /* asii */
+ if (ntlm_extract_string(domainname, (unsigned char*) msg, msglen,
+ msg->dom_off, msg->dom_len, MAX_DOMLEN))
+ return 64;
+ }
+ return 0;
+}
+
+int
+ntlmssp_decode_msg(struct ntlmssp_info *info,
+ unsigned char *raw_msg, unsigned msglen, unsigned *ntlmssp_flags)
+{
+ switch (info->msg_type = ntlm_msg_type(raw_msg, msglen)) {
+ case 1:
+ return ntlm_msg1_getntlmssp_flags(raw_msg,(unsigned char*)ntlmssp_flags)
+ + ntlm_msg1_gethostname(raw_msg, msglen, info->host)
+ + ntlm_msg1_getdomainname(raw_msg, msglen, info->domain);
+ case 3:
+ return ntlm_msg3_getlm(raw_msg, msglen, info->lm)
+ + ntlm_msg3_getnt(raw_msg, msglen, info->nt)
+ + ntlm_msg3_getusername(raw_msg, msglen, info->user,*ntlmssp_flags)
+ + ntlm_msg3_gethostname(raw_msg, msglen, info->host,*ntlmssp_flags)
+ + ntlm_msg3_getdomainname(raw_msg, msglen, info->domain,*ntlmssp_flags);
+ }
+ return -1;
+}
+
+int
+ntlmssp_encode_msg2(unsigned char *nonce, struct ntlm_msg2 *msg)
+{
+ memset(msg, 0, sizeof(struct ntlm_msg2));
+ strcpy((char*)msg->protocol, "NTLMSSP");
+ msg->type = 0x02;
+ set_little_endian_word(msg->msg_len, sizeof(struct ntlm_msg2));
+ set_little_endian_word(msg->flags, 0x8201);
+ memcpy(msg->nonce, nonce, sizeof(msg->nonce));
+ return 0;
+}
+
+int
+ntlmssp_encode_msg2_win9x(unsigned char *nonce, struct ntlm_msg2_win9x *msg,char *domainname,unsigned ntlmssp_flags)
+{
+ unsigned int size,len,flags;
+
+ memset(msg, 0, sizeof(struct ntlm_msg2_win9x));
+ strcpy((char*)msg->protocol, "NTLMSSP");
+ msg->type = 0x02;
+ if (ntlmssp_flags & NTLMSSP_NEGOTIATE_UNICODE) {
+ /* unicode case */
+
+ len=strlen(domainname);
+ ntlm_put_in_unicode((unsigned char*)msg->dom, (unsigned char*)domainname,
+ len, MAX_DOMLEN);
+ len=len*2;
+ if (len>MAX_DOMLEN)
+ len=MAX_DOMLEN; /* fhz: bad very bad */
+ flags=NTLM_NTLMSSP_NEG_FLAGS | NTLMSSP_NEGOTIATE_UNICODE;
+ } else {
+ /* ascii case */
+ len=strlen(domainname);
+ if (len>MAX_DOMLEN)
+ len=MAX_DOMLEN; /* fhz: bad very bad */
+ strncpy((char*)msg->dom, domainname,len);
+ flags=NTLM_NTLMSSP_NEG_FLAGS;
+ }
+ size=NTLM_MSG2_WIN9X_FIXED_SIZE+len;
+ set_little_endian_word(msg->dom_off, NTLM_MSG2_WIN9X_FIXED_SIZE);
+ set_little_endian_word(msg->dom_len1,len);
+ set_little_endian_word(msg->dom_len2,len);
+ set_little_endian_word(msg->msg_len,size);
+ set_little_endian_word(msg->flags,flags);
+ if (ntlmssp_flags & NTLMSSP_REQUEST_TARGET)
+ set_little_endian_word(msg->zero2, 0x01); /* == set NTLMSSP_TARGET_TYPE_DOMAIN */
+
+ memcpy(msg->nonce, nonce, sizeof(msg->nonce));
+ return size;
+}
+
+
+int
+ntlmssp_validuser(const char *USERNAME, const char *PASSWORD, const char *SERVER,
+ const char *BACKUP, const char *DOMAIN)
+{
+ char *SMB_Prots[] =
+ {"PC NETWORK PROGRAM 1.0",
+ "MICROSOFT NETWORKS 1.03",
+ "MICROSOFT NETWORKS 3.0",
+ "LANMAN1.0",
+ "LM1.2X002",
+ "Samba",
+ "NT LM 0.12",
+ "NT LANMAN 1.0",
+ NULL};
+ SMB_Handle_Type con;
+
+ SMB_Init();
+ con = SMB_Connect_Server(NULL, (char*)SERVER, (char*)DOMAIN);
+ if (con == NULL) { /* Error ... */
+ con = SMB_Connect_Server(NULL, (char*)BACKUP, (char*)DOMAIN);
+ if (con == NULL) {
+ return (NTV_SERVER_ERROR);
+ }
+ }
+ if (SMB_Negotiate(con, SMB_Prots) < 0) { /* An error */
+ SMB_Discon(con, 0);
+ return (NTV_PROTOCOL_ERROR);
+ }
+ /* Test for a server in share level mode do not authenticate against
+ * it */
+ if (con->Security == 0) {
+ SMB_Discon(con, 0);
+ return (NTV_PROTOCOL_ERROR);
+ }
+ if (SMB_Logon_Server(con, (char*)USERNAME, (char*)PASSWORD, 0) < 0) {
+ SMB_Discon(con, 0);
+ return (NTV_LOGON_ERROR);
+ }
+ SMB_Discon(con, 0);
+ return (NTV_NO_ERROR);
+}
+
+void* ntlmssp_connect(const char *SERVER, const char *BACKUP, const char *DOMAIN,
+ char *nonce)
+{
+ char *SMB_Prots[] =
+ {"PC NETWORK PROGRAM 1.0",
+ "MICROSOFT NETWORKS 1.03",
+ "MICROSOFT NETWORKS 3.0",
+ "LANMAN1.0",
+ "LM1.2X002",
+ "Samba",
+ "NT LM 0.12",
+ "NT LANMAN 1.0",
+ NULL};
+ SMB_Handle_Type con;
+
+ SMB_Init();
+ con = SMB_Connect_Server(NULL, (char*)SERVER, (char*)DOMAIN);
+ if (con == NULL) { /* Error ... */
+ con = SMB_Connect_Server(NULL, (char*)BACKUP, (char*)DOMAIN);
+ if (con == NULL) {
+ return (NULL);
+ }
+ }
+ if (SMB_Negotiate(con, SMB_Prots) < 0) { /* An error */
+ SMB_Discon(con, 0);
+ return (NULL);
+ }
+ /* Test for a server in share level mode do not authenticate
+ * against it */
+ if (con->Security == 0) {
+ SMB_Discon(con, 0);
+ return (NULL);
+ }
+ memcpy(nonce, con->Encrypt_Key, 8);
+
+ return con;
+}
+
+int
+ntlmssp_auth(void *handle, const char *USERNAME, const char *PASSWORD, int flag)
+{
+ SMB_Handle_Type con = handle;
+
+ if (SMB_Logon_Server(con, (char*)USERNAME, (char*)PASSWORD, flag) < 0) {
+ return (NTV_LOGON_ERROR);
+ }
+ return NTV_NO_ERROR;
+}
+
+void
+ntlmssp_disconnect(void *handle)
+{
+ SMB_Handle_Type con = handle;
+ SMB_Discon(con, 0);
+}
+