changeset 13084:31a3a9af1494

[gaim-migrate @ 15446] simple: successfully register at MS LCS no presence working at the moment committer: Tailor Script <tailor@pidgin.im>
author Thomas Butter <tbutter>
date Tue, 31 Jan 2006 21:02:52 +0000
parents 1b81ab9c8441
children 3382d7aa9ca3
files src/ntlm.c src/ntlm.h src/protocols/simple/simple.c src/protocols/simple/simple.h src/proxy.c
diffstat 5 files changed, 107 insertions(+), 36 deletions(-) [+]
line wrap: on
line diff
--- a/src/ntlm.c	Tue Jan 31 20:21:49 2006 +0000
+++ b/src/ntlm.c	Tue Jan 31 21:02:52 2006 +0000
@@ -30,6 +30,8 @@
 #include "cipher.h"
 #include <string.h>
 
+#define NTLM_NEGOTIATE_NTLM2_KEY 0x00080000
+
 struct type1_message {
 	guint8  protocol[8];     /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0' */
 	guint8  type;            /* 0x01 */
@@ -59,8 +61,7 @@
 	guint8  zero1[7];
 	short   msg_len;         /* 0x28 */
 	guint8  zero2[2];
-	short   flags;           /* 0x8201 */
-	guint8  zero3[2];
+	guint32   flags;           /* 0x8201 */
 
 	guint8  nonce[8];        /* nonce */
 	guint8  zero[8];
@@ -94,13 +95,16 @@
 	short   host_len1;       /* host string length */
 	short   host_len2;       /* host string length */
 	short   host_off;        /* host string offset */
-	guint8  zero6[6];
+	guint8  zero6[2];
 
-	short   msg_len;         /* message length */
+	short   sess_len1;
+	short	sess_len2;
+	short   sess_off;         /* message length */
 	guint8  zero7[2];
 
-	short   flags;           /* 0x8201 */
-	guint8  zero8[2];
+	guint32   flags;           /* 0x8201 */
+/*	guint32  flags2;  unknown, used in windows messenger
+	guint32  flags3; */
 
 #if 0
 	guint8  dom[*];          /* domain string (unicode UTF-16LE) */
@@ -134,11 +138,12 @@
 	return gaim_base64_encode((guchar*)msg, sizeof(struct type1_message) + strlen(hostname) + strlen(domain));
 }
 
-gchar *gaim_ntlm_parse_type2(gchar *type2) {
+gchar *gaim_ntlm_parse_type2(gchar *type2, guint32 *flags) {
 	gsize retlen;
 	static gchar nonce[8];
 	struct type2_message *tmsg = (struct type2_message*)gaim_base64_decode((char*)type2, &retlen);
 	memcpy(nonce, tmsg->nonce, 8);
+	if(flags) *flags = tmsg->flags;
 	g_free(tmsg);
 	return nonce;
 }
@@ -188,12 +193,22 @@
 	des_ecb_encrypt((char*)plaintext, (char*)(results+16), (char*)key);
 }
 
-gchar *gaim_ntlm_gen_type3(gchar *username, gchar *passw, gchar *hostname, gchar *domain, gchar *nonce) {
+char sesskey[16] = { (char) 0xff, (char) 0xff, (char) 0xad,
+	                (char) 0xf5, (char) 0xc8, (char) 0xff,
+	                (char) 0x67, (char) 0x66, (char) 0xf6,
+	                (char) 0x80, (char) 0xe8, (char) 0x34,
+	                (char) 0xd7, (char) 0x8d, (char) 0x28,
+	                (char) 0x2b };
+
+gchar *gaim_ntlm_gen_type3(gchar *username, gchar *passw, gchar *hostname, gchar *domain, gchar *nonce, guint32 *flags) {
 	char  lm_pw[14];
 	unsigned char lm_hpw[21];
+	gchar *sessionnonce = nonce;
 	gchar key[8];
-	struct type3_message *tmsg = g_malloc0(sizeof(struct type3_message)+
-		strlen(domain) + strlen(username) + strlen(hostname) + 24 +24);
+	int msglen = sizeof(struct type3_message)+
+		strlen(domain) + strlen(username)+
+		strlen(hostname) + 24 +24 + ((flags) ? 16 : 0);
+	struct type3_message *tmsg = g_malloc0(msglen);
 	int   len = strlen(passw);
 	unsigned char lm_resp[24], nt_resp[24];
 	unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
@@ -228,7 +243,11 @@
 	tmsg->host_len1 = tmsg->host_len2 = strlen(hostname);
 	tmsg->host_off = sizeof(struct type3_message) + strlen(domain) + strlen(username);
 
-	tmsg->msg_len = sizeof(struct type3_message) + strlen(domain) + strlen(username) + strlen(hostname) + 0x18 + 0x18;
+	if(flags) {
+		tmsg->sess_off = sizeof(struct type3_message) + strlen(domain) + strlen(username) + strlen(hostname) + 0x18 + 0x18;
+		tmsg->sess_len1 = tmsg->sess_len2 = 0x10;
+	}
+
 	tmsg->flags = 0x8200;
 
 	tmp = ((char*) tmsg) + sizeof(struct type3_message);
@@ -239,8 +258,9 @@
 	strcpy(tmp, hostname);
 	tmp += strlen(hostname);
 	
+	/* LM */
 	if (len > 14)  len = 14;
-	
+
 	for (idx=0; idx<len; idx++)
 		lm_pw[idx] = g_ascii_toupper(passw[idx]);
 	for (; idx<14; idx++)
@@ -253,8 +273,9 @@
 	des_ecb_encrypt((char*)magic, (char*)lm_hpw+8, (char*)key);
 
 	memset(lm_hpw+16, 0, 5);
+	calc_resp(lm_hpw, (guchar*)sessionnonce, lm_resp);
 
-
+	/* NTLM */
 	lennt = strlen(passw);
 	for (idx=0; idx<lennt; idx++)
 	{
@@ -271,11 +292,23 @@
 	memset(nt_hpw+16, 0, 5);
 
 
-	calc_resp(lm_hpw, (guchar*)nonce, lm_resp);
-	calc_resp(nt_hpw, (guchar*)nonce, nt_resp);
+	calc_resp(nt_hpw, (guchar*)sessionnonce, nt_resp);
 	memcpy(tmp, lm_resp, 0x18);
-	memcpy(tmp+0x18, nt_resp, 0x18);
-	tmp = gaim_base64_encode((guchar*) tmsg, tmsg->msg_len);
+	tmp += 0x18;
+	memcpy(tmp, nt_resp, 0x18);
+	tmp += 0x18;
+
+
+	/* LCS Stuff */
+	if(flags) {
+		tmsg->flags = 0x409082d4;
+		memcpy(tmp, sesskey, 0x10);
+	}
+
+	/*tmsg->flags2 = 0x0a280105;
+	tmsg->flags3 = 0x0f000000;*/
+	
+	tmp = gaim_base64_encode((guchar*) tmsg, msglen);
 	g_free(tmsg);
 	return tmp;
 }
--- a/src/ntlm.h	Tue Jan 31 20:21:49 2006 +0000
+++ b/src/ntlm.h	Tue Jan 31 21:02:52 2006 +0000
@@ -41,7 +41,7 @@
  * @param type2 String containing the base64 encoded type2 message
  * @return The nonce for use in message type3
  */
-gchar *gaim_ntlm_parse_type2(gchar *type2);
+gchar *gaim_ntlm_parse_type2(gchar *type2, guint32 *flags);
 
 /**
  * Generates a type3 message
@@ -51,8 +51,9 @@
  * @param hostname The hostname
  * @param domain The domain to authenticate against
  * @param nonce The nonce returned by gaim_ntlm_parse_type2
+ * @param flags Pointer to the flags returned by gaim_ntlm_parse_type2
  * @return A base64 encoded type3 message
  */
-gchar *gaim_ntlm_gen_type3(gchar *username, gchar *passw, gchar *hostname, gchar *domain, gchar *nonce);
+gchar *gaim_ntlm_gen_type3(gchar *username, gchar *passw, gchar *hostname, gchar *domain, gchar *nonce, guint32 *flags);
 
 #endif /* _GAIM_NTLM_H */
--- a/src/protocols/simple/simple.c	Tue Jan 31 20:21:49 2006 +0000
+++ b/src/protocols/simple/simple.c	Tue Jan 31 21:02:52 2006 +0000
@@ -45,6 +45,7 @@
 #include "ntlm.h"
 
 static char *gentag() {
+//	return g_strdup("0e3f151");
 	return g_strdup_printf("%04d%04d", rand() & 0xFFFF, rand() & 0xFFFF);
 }
 
@@ -265,6 +266,11 @@
 	gchar *response;
 	gchar *ret;
 	gchar *tmp;
+	char *authdomain = gaim_account_get_string(sip->account, "authdomain", "");
+	char *authuser = gaim_account_get_string(sip->account, "authuser", sip->username);
+	if(!authuser || strlen(authuser)<1) {
+		authuser = sip->username;
+	}
 
 	if(auth->type == 1) { /* Digest */
 		sprintf(noncecount, "%08d", auth->nc++);
@@ -273,19 +279,17 @@
 							auth->nonce, noncecount, NULL, auth->digest_session_key);
 		gaim_debug(GAIM_DEBUG_MISC, "simple", "response %s\n", response);
 
-		ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n", sip->username, auth->realm, auth->nonce, target, noncecount, response);
+		ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n", authuser, auth->realm, auth->nonce, target, noncecount, response);
 		g_free(response);
 		return ret;
 	} else if(auth->type == 2) { /* NTLM */
-		if(auth->nc == 3) {
-			ret = gaim_ntlm_gen_type3(sip->username, sip->password, "gaim", sip->servername, auth->nonce);
-			tmp = g_strdup_printf("NTLM qop=\"auth\" realm=\"%s\" targetname=\"%s\" response=\"%s\"\r\n", auth->realm, auth->target, ret);
+		if(auth->nc == 3 && auth->nonce) {
+			ret = gaim_ntlm_gen_type3(authuser, sip->password, "gaim", authdomain, auth->nonce, &auth->flags);
+			tmp = g_strdup_printf("NTLM qop=\"auth\", opaque=\"%s\", realm=\"%s\", targetname=\"%s\", gssapi-data=\"%s\"\r\n", auth->opaque, auth->realm, auth->target, ret);
 			g_free(ret);
 			return tmp;
 		}
-		ret = gaim_ntlm_gen_type1("gaim", sip->servername);
-		tmp = g_strdup_printf("NTLM qop=\"auth\" realm=\"%s\" targetname=\"%s\" response=\"%s\"\r\n", auth->realm, auth->target, ret);
-		g_free(ret);
+		tmp = g_strdup_printf("NTLM qop=\"auth\", realm=\"%s\", targetname=\"%s\", gssapi-data=\"\"\r\n", auth->realm, auth->target);
 		return tmp;
 	}
 
@@ -295,7 +299,7 @@
 						auth->nonce, noncecount, NULL, auth->digest_session_key);
 	gaim_debug(GAIM_DEBUG_MISC, "simple", "response %s\n", response);
 
-	ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n", sip->username, auth->realm, auth->nonce, target, noncecount, response);
+	ret = g_strdup_printf("Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", nc=\"%s\", response=\"%s\"\r\n", authuser, auth->realm, auth->nonce, target, noncecount, response);
 	g_free(response);
 	return ret;
 }
@@ -316,8 +320,14 @@
 
 static void fill_auth(struct simple_account_data *sip, gchar *hdr, struct sip_auth *auth) {
 	int i=0;
+	char *authuser = gaim_account_get_string(sip->account, "authuser", sip->username);
 	char *tmp;
 	gchar **parts;
+
+	if(!authuser || strlen(authuser)<1) {
+		authuser = sip->username;
+	}
+	
 	if(!hdr) {
 		gaim_debug_error("simple", "fill_auth: hdr==NULL\n");
 		return;
@@ -326,9 +336,13 @@
 	if(!g_strncasecmp(hdr, "NTLM", 4)) {
 		gaim_debug_info("simple", "found NTLM\n");
 		auth->type = 2;
-		if(!auth->nonce && !auth->nc) {
+		if(!strstr(hdr, "gssapi-data")) {
+			gaim_debug_info("simple","here");
 			parts = g_strsplit(hdr, " ", 0);
+			i = 0;
+			auth->realm = "SIP Communications Service";
 			while(parts[i]) {
+			gaim_debug_info("simple","parts[i] %s\n",parts[i]);
 				if((tmp = parse_attribute("targetname=\"",
 						parts[i]))) {
 					auth->target = tmp;
@@ -340,12 +354,22 @@
 				i++;
 			}
 			g_strfreev(parts);
-			parts = NULL;
 			auth->nc = 1;
-		}
-		if(!auth->nonce && auth->nc==2) {
+		} else {
 			auth->nc = 3;
-			auth->nonce = gaim_ntlm_parse_type2(hdr+5);
+			i = 0;
+			parts = g_strsplit(hdr, " ", 0);
+			while(parts[i]) {
+				if((tmp = parse_attribute("gssapi-data=\"", parts[i]))) {
+					auth->nonce = g_strdup(gaim_ntlm_parse_type2(tmp, &auth->flags));
+					g_free(tmp);
+				}
+				if((tmp = parse_attribute("opaque=\"", parts[i]))) {
+					auth->opaque = tmp;
+				}
+				i++;
+			}
+			g_strfreev(parts);
 		}
 		return;
 	}
@@ -366,7 +390,7 @@
 	gaim_debug(GAIM_DEBUG_MISC, "simple", "nonce: %s realm: %s ", auth->nonce ? auth->nonce : "(null)", auth->realm ? auth->realm : "(null)");
 
 	auth->digest_session_key = gaim_cipher_http_digest_calculate_session_key(
-			"md5", sip->username, auth->realm, sip->password, auth->nonce, NULL);
+			"md5", authuser, auth->realm, sip->password, auth->nonce, NULL);
 
 	auth->nc=1;
 }
@@ -545,7 +569,8 @@
 
 	buf = g_strdup_printf("%s %s SIP/2.0\r\n"
 			"Via: SIP/2.0/%s %s:%d;branch=%s\r\n"
-			"From: <sip:%s@%s>;tag=%s\r\n"
+			/* Don't know what epid is, but LCS wants it */
+			"From: <sip:%s@%s>;tag=%s;epid=1234567890\r\n"
 			"To: <%s>%s%s\r\n"
 			"Max-Forwards: 10\r\n"
 			"CSeq: %d %s\r\n"
@@ -1374,9 +1399,15 @@
 		g_free(sip->username);
 		g_free(sip->password);
 		g_free(sip->registrar.nonce);
+		g_free(sip->registrar.opaque);
+		g_free(sip->registrar.target);
 		g_free(sip->registrar.realm);
+		g_free(sip->registrar.digest_session_key);
 		g_free(sip->proxy.nonce);
+		g_free(sip->proxy.opaque);
+		g_free(sip->proxy.target);
 		g_free(sip->proxy.realm);
+		g_free(sip->proxy.digest_session_key);
 		g_free(sip->sendlater);
 		g_free(sip->realhostname);
 		if(sip->listenpa) gaim_input_remove(sip->listenpa);
@@ -1511,6 +1542,10 @@
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 	option = gaim_account_option_string_new(_("Proxy"), "proxy", "");
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	option = gaim_account_option_string_new(_("Auth User"), "authuser", "");
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+	option = gaim_account_option_string_new(_("Auth Domain"), "authdomain", "");
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
 }
 
 GAIM_INIT_PLUGIN(simple, _init_plugin, info);
--- a/src/protocols/simple/simple.h	Tue Jan 31 20:21:49 2006 +0000
+++ b/src/protocols/simple/simple.h	Tue Jan 31 21:02:52 2006 +0000
@@ -53,8 +53,10 @@
 struct sip_auth {
 	int type; /* 1 = Digest / 2 = NTLM */
 	gchar *nonce;
+	gchar *opaque;
 	gchar *realm;
 	gchar *target;
+	guint32 flags;
 	int nc;
 	gchar *digest_session_key;
 	int retries;
--- a/src/proxy.c	Tue Jan 31 20:21:49 2006 +0000
+++ b/src/proxy.c	Tue Jan 31 21:02:52 2006 +0000
@@ -1136,8 +1136,8 @@
 				ntlm += strlen("Proxy-Authenticate: NTLM ");
 				while(*nonce != '\r' && *nonce != '\0') nonce ++;
 				*nonce = 0;
-				nonce = gaim_ntlm_parse_type2(ntlm);
-				response = gaim_ntlm_gen_type3(username, (gchar*)gaim_proxy_info_get_password(phb->gpi), (gchar*)gaim_proxy_info_get_host(phb->gpi), domain, nonce);
+				nonce = gaim_ntlm_parse_type2(ntlm, NULL);
+				response = gaim_ntlm_gen_type3(username, (gchar*)gaim_proxy_info_get_password(phb->gpi), (gchar*)gaim_proxy_info_get_host(phb->gpi), domain, nonce, NULL);
 				username--;
 				*username = '\\';
 				request = g_strdup_printf("CONNECT %s:%d HTTP/1.1\r\nHost: %s:%d\r\nProxy-Authorization: NTLM %s\r\nProxy-Connection: Keep-Alive\r\n\r\n",