# HG changeset patch # User Thomas Butter # Date 1138741372 0 # Node ID 31a3a9af14944b18ff5d049c4950a187e155af4d # Parent 1b81ab9c84410535af1750ce9b6e5910003b85fb [gaim-migrate @ 15446] simple: successfully register at MS LCS no presence working at the moment committer: Tailor Script diff -r 1b81ab9c8441 -r 31a3a9af1494 src/ntlm.c --- 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 +#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; idxmsg_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; } diff -r 1b81ab9c8441 -r 31a3a9af1494 src/ntlm.h --- 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 */ diff -r 1b81ab9c8441 -r 31a3a9af1494 src/protocols/simple/simple.c --- 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: ;tag=%s\r\n" + /* Don't know what epid is, but LCS wants it */ + "From: ;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); diff -r 1b81ab9c8441 -r 31a3a9af1494 src/protocols/simple/simple.h --- 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; diff -r 1b81ab9c8441 -r 31a3a9af1494 src/proxy.c --- 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",