diff options
author | Stef Walter <stef@memberwebs.com> | 2006-05-10 17:33:18 +0000 |
---|---|---|
committer | Stef Walter <stef@memberwebs.com> | 2006-05-10 17:33:18 +0000 |
commit | f5164b1be2a17e2dba5908f08ba270cf035d6546 (patch) | |
tree | 85c5d7973851d9f3105e92b900a50a43c12f1a94 /daemon/ntlmssp.c | |
parent | e593016a80ceee52b6e3244512ff4307f8c208fa (diff) |
Some missing files
Diffstat (limited to 'daemon/ntlmssp.c')
-rw-r--r-- | daemon/ntlmssp.c | 444 |
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); +} + |