Changeset 523fb23 for protocols/msn
- Timestamp:
- 2010-08-11T08:08:39Z (14 years ago)
- Branches:
- master
- Children:
- 7f34ce2
- Parents:
- 7db65b7
- Location:
- protocols/msn
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
protocols/msn/Makefile
r7db65b7 r523fb23 43 43 @$(LD) $(LFLAGS) $(objects) -o msn_mod.o 44 44 45 45 soap.o: soap.h soap.c -
protocols/msn/msn.c
r7db65b7 r523fb23 103 103 g_free( md->grouplist[--md->groupcount] ); 104 104 g_free( md->grouplist ); 105 g_free( md->passport_token ); 105 g_free( md->tokens[0] ); 106 g_free( md->tokens[1] ); 106 107 g_free( md->lock_key ); 107 108 -
protocols/msn/msn.h
r7db65b7 r523fb23 76 76 77 77 int trId; 78 char * passport_token;78 char *tokens[2]; 79 79 char *lock_key; 80 80 … … 171 171 /* ns.c */ 172 172 gboolean msn_ns_connected( gpointer data, gint source, b_input_condition cond ); 173 void msn_auth_got_passport_token( struct im_connection *ic, char *token ); 173 174 174 175 /* msn_util.c */ -
protocols/msn/msn_util.c
r7db65b7 r523fb23 33 33 struct msn_data *md = ic->proto_data; 34 34 int st; 35 36 if( getenv( "BITLBEE_DEBUG" ) ) 37 { 38 write( 2, "->NS:", 5 ); 39 write( 2, s, len ); 40 } 35 41 36 42 st = write( md->fd, s, len ); … … 280 286 if( st <= 0 ) 281 287 return( -1 ); 288 289 if( getenv( "BITLBEE_DEBUG" ) ) 290 { 291 write( 2, "->C:", 4 ); 292 write( 2, h->rxq + h->rxlen - st, st ); 293 } 282 294 283 295 while( st ) … … 446 458 } 447 459 448 unsigned int little_endian( unsigned int dw )449 {450 #if defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN451 return dw;452 #else453 /* We're still not sure if this machine is big endian since the454 constants above are not that portable. Don't swap bytes, just455 force-compose a 32-bit little endian integer. */456 unsigned int ret = 0, i;457 char *dst = (char*) (&ret + 1);458 459 for (i = 0; i < 4; i ++)460 {461 *(--dst) = dw >> 24;462 dw <<= 8;463 }464 465 return ret;466 #endif467 }468 469 460 /* Copied and heavily modified from http://tmsnc.sourceforge.net/chl.c */ 470 461 char *msn_p11_challenge( char *challenge ) … … 487 478 for (i = 0; i < 4; i ++) 488 479 { 489 md5Parts[i] = little_endian(md5Parts[i]);480 md5Parts[i] = GUINT32_TO_LE(md5Parts[i]); 490 481 491 482 /* & each integer with 0x7FFFFFFF */ … … 508 499 long long temp; 509 500 510 chlStringParts[i] = little_endian(chlStringParts[i]);511 chlStringParts[i+1] = little_endian(chlStringParts[i+1]);501 chlStringParts[i] = GUINT32_TO_LE(chlStringParts[i]); 502 chlStringParts[i+1] = GUINT32_TO_LE(chlStringParts[i+1]); 512 503 513 504 temp = (md5Parts[0] * (((0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF)+nHigh) + md5Parts[1])%0x7FFFFFFF; … … 525 516 /* swap more bytes if big endian */ 526 517 for (i = 0; i < 4; i ++) 527 newHashParts[i] = little_endian(newHashParts[i]);518 newHashParts[i] = GUINT32_TO_LE(newHashParts[i]); 528 519 529 520 /* make a string of the parts */ -
protocols/msn/ns.c
r7db65b7 r523fb23 35 35 static int msn_ns_message( gpointer data, char *msg, int msglen, char **cmd, int num_parts ); 36 36 37 static void msn_auth_got_passport_token( struct msn_auth_data *mad );38 37 static gboolean msn_ns_got_display_name( struct im_connection *ic, char *name ); 39 38 … … 74 73 md->handler->rxq = g_new0( char, 1 ); 75 74 76 g_snprintf( s, sizeof( s ), "VER %d MSNP1 4CVR0\r\n", ++md->trId );75 g_snprintf( s, sizeof( s ), "VER %d MSNP15 CVR0\r\n", ++md->trId ); 77 76 if( msn_write( ic, s, strlen( s ) ) ) 78 77 { … … 114 113 if( strcmp( cmd[0], "VER" ) == 0 ) 115 114 { 116 if( cmd[2] && strncmp( cmd[2], "MSNP1 4", 5 ) != 0 )115 if( cmd[2] && strncmp( cmd[2], "MSNP15", 5 ) != 0 ) 117 116 { 118 117 imcb_error( ic, "Unsupported protocol" ); … … 128 127 { 129 128 /* We don't give a damn about the information we just received */ 130 g_snprintf( buf, sizeof( buf ), "USR %d TWNI %s\r\n", ++md->trId, ic->acc->user );129 g_snprintf( buf, sizeof( buf ), "USR %d SSO I %s\r\n", ++md->trId, ic->acc->user ); 131 130 return( msn_write( ic, buf, strlen( buf ) ) ); 132 131 } … … 221 220 else if( strcmp( cmd[0], "USR" ) == 0 ) 222 221 { 223 if( num_parts == 5 && strcmp( cmd[2], "TWN" ) == 0 && strcmp( cmd[3], "S" ) == 0 ) 224 { 225 /* Time for some Passport black magic... */ 226 if( !passport_get_token( msn_auth_got_passport_token, ic, ic->acc->user, ic->acc->pass, cmd[4] ) ) 227 { 228 imcb_error( ic, "Error while contacting Passport server" ); 229 imc_logout( ic, TRUE ); 230 return( 0 ); 231 } 222 if( num_parts >= 6 && strcmp( cmd[2], "SSO" ) == 0 && 223 strcmp( cmd[3], "S" ) == 0 ) 224 { 225 msn_soap_passport_sso_request( ic, cmd[4], cmd[5] ); 232 226 } 233 227 else if( strcmp( cmd[2], "OK" ) == 0 ) … … 775 769 } 776 770 777 static void msn_auth_got_passport_token( struct msn_auth_data *mad)771 void msn_auth_got_passport_token( struct im_connection *ic, char *token ) 778 772 { 779 struct im_connection *ic = mad->data;780 773 struct msn_data *md; 781 774 … … 785 778 786 779 md = ic->proto_data; 787 if( mad->token )780 788 781 { 789 782 char buf[1024]; 790 783 791 md->passport_token = g_strdup( mad->token ); 792 793 g_snprintf( buf, sizeof( buf ), "USR %d TWN S %s\r\n", ++md->trId, mad->token ); 784 g_snprintf( buf, sizeof( buf ), "USR %d SSO S %s %s\r\n", ++md->trId, md->tokens[0], token ); 794 785 msn_write( ic, buf, strlen( buf ) ); 795 }796 else797 {798 imcb_error( ic, "Error during Passport authentication: %s", mad->error );799 imc_logout( ic, TRUE );800 786 } 801 787 } -
protocols/msn/sb.c
r7db65b7 r523fb23 39 39 { 40 40 int st; 41 42 if( getenv( "BITLBEE_DEBUG" ) ) 43 { 44 write( 2, "->SB:", 5 ); 45 write( 2, s, len ); 46 } 41 47 42 48 st = write( sb->fd, s, len ); -
protocols/msn/soap.c
r7db65b7 r523fb23 28 28 #include "url.h" 29 29 #include "misc.h" 30 #include "sha1.h" 30 31 #include "base64.h" 31 32 #include "xmltree.h" … … 83 84 static int msn_soap_send_request( struct msn_soap_req_data *soap_req ) 84 85 { 85 struct msn_data *md = soap_req->ic->proto_data;86 86 char *http_req; 87 char * pom, *s;87 char *soap_action = NULL; 88 88 url_t url; 89 89 90 90 soap_req->build_request( soap_req ); 91 91 92 pom = g_new0( char, strlen( md->passport_token ) * 3 ); 93 strcpy( pom, md->passport_token + 2 ); 94 if( ( s = strchr( pom, '&' ) ) ) 95 *s = '\0'; 92 if( soap_req->action ) 93 soap_action = g_strdup_printf( "SOAPAction: \"%s\"\r\n", soap_req->action ); 96 94 97 95 url_set( &url, soap_req->url ); 98 96 http_req = g_strdup_printf( SOAP_HTTP_REQUEST, url.file, url.host, 99 soap_ req->action, pom,97 soap_action ? soap_action : "", 100 98 strlen( soap_req->payload ), soap_req->payload ); 101 99 … … 104 102 105 103 g_free( http_req ); 104 g_free( soap_action ); 106 105 107 106 return soap_req->http_req != NULL; … … 140 139 141 140 141 /* passport_sso: Authentication MSNP15+ */ 142 143 struct msn_soap_passport_sso_data 144 { 145 char *policy; 146 char *nonce; 147 char *secret; 148 }; 149 150 static int msn_soap_passport_sso_build_request( struct msn_soap_req_data *soap_req ) 151 { 152 struct msn_soap_passport_sso_data *sd = soap_req->data; 153 struct im_connection *ic = soap_req->ic; 154 155 soap_req->url = g_strdup( SOAP_PASSPORT_SSO_URL ); 156 soap_req->payload = g_markup_printf_escaped( SOAP_PASSPORT_SSO_PAYLOAD, 157 ic->acc->user, ic->acc->pass, sd->policy ); 158 159 return MSN_SOAP_OK; 160 } 161 162 static xt_status msn_soap_passport_sso_token( struct xt_node *node, gpointer data ) 163 { 164 struct msn_soap_req_data *soap_req = data; 165 struct msn_soap_passport_sso_data *sd = soap_req->data; 166 struct msn_data *md = soap_req->ic->proto_data; 167 struct xt_node *p; 168 char *id; 169 170 if( ( id = xt_find_attr( node, "Id" ) ) == NULL ) 171 return XT_HANDLED; 172 id += strlen( id ) - 1; 173 if( *id == '1' && 174 ( p = node->parent ) && ( p = p->parent ) && 175 ( p = xt_find_node( p->children, "wst:RequestedProofToken" ) ) && 176 ( p = xt_find_node( p->children, "wst:BinarySecret" ) ) && 177 p->text ) 178 sd->secret = g_strdup( p->text ); 179 180 if( *id == '1' ) 181 md->tokens[0] = g_strdup( node->text ); 182 else if( *id == '2' ) 183 md->tokens[1] = g_strdup( node->text ); 184 185 return XT_HANDLED; 186 } 187 188 static const struct xt_handler_entry msn_soap_passport_sso_parser[] = { 189 { "wsse:BinarySecurityToken", "wst:RequestedSecurityToken", msn_soap_passport_sso_token }, 190 { NULL, NULL, NULL } 191 }; 192 193 static char *msn_key_fuckery( char *key, int key_len, char *type ) 194 { 195 unsigned char hash1[20+strlen(type)+1]; 196 unsigned char hash2[20]; 197 char *ret; 198 199 sha1_hmac( key, key_len, type, 0, hash1 ); 200 strcpy( (char*) hash1 + 20, type ); 201 sha1_hmac( key, key_len, (char*) hash1, sizeof( hash1 ) - 1, hash2 ); 202 203 /* This is okay as hash1 is read completely before it's overwritten. */ 204 sha1_hmac( key, key_len, (char*) hash1, 20, hash1 ); 205 sha1_hmac( key, key_len, (char*) hash1, sizeof( hash1 ) - 1, hash1 ); 206 207 ret = g_malloc( 24 ); 208 memcpy( ret, hash2, 20 ); 209 memcpy( ret + 20, hash1, 4 ); 210 return ret; 211 } 212 213 static int msn_soap_passport_sso_handle_response( struct msn_soap_req_data *soap_req ) 214 { 215 struct msn_soap_passport_sso_data *sd = soap_req->data; 216 struct im_connection *ic = soap_req->ic; 217 char *key1, *key2, *key3, *blurb64; 218 int key1_len; 219 unsigned char *padnonce, *des3res; 220 struct 221 { 222 unsigned int uStructHeaderSize; // 28. Does not count data 223 unsigned int uCryptMode; // CRYPT_MODE_CBC (1) 224 unsigned int uCipherType; // TripleDES (0x6603) 225 unsigned int uHashType; // SHA1 (0x8004) 226 unsigned int uIVLen; // 8 227 unsigned int uHashLen; // 20 228 unsigned int uCipherLen; // 72 229 unsigned char iv[8]; 230 unsigned char hash[20]; 231 unsigned char cipherbytes[72]; 232 } blurb = { 233 GUINT32_TO_LE( 28 ), 234 GUINT32_TO_LE( 1 ), 235 GUINT32_TO_LE( 0x6603 ), 236 GUINT32_TO_LE( 0x8004 ), 237 GUINT32_TO_LE( 8 ), 238 GUINT32_TO_LE( 20 ), 239 GUINT32_TO_LE( 72 ), 240 }; 241 242 key1_len = base64_decode( sd->secret, (unsigned char**) &key1 ); 243 244 key2 = msn_key_fuckery( key1, key1_len, "WS-SecureConversationSESSION KEY HASH" ); 245 key3 = msn_key_fuckery( key1, key1_len, "WS-SecureConversationSESSION KEY ENCRYPTION" ); 246 247 sha1_hmac( key2, 24, sd->nonce, 0, blurb.hash ); 248 padnonce = g_malloc( strlen( sd->nonce ) + 8 ); 249 strcpy( (char*) padnonce, sd->nonce ); 250 memset( padnonce + strlen( sd->nonce ), 8, 8 ); 251 252 random_bytes( blurb.iv, 8 ); 253 254 ssl_des3_encrypt( (unsigned char*) key3, 24, padnonce, strlen( sd->nonce ) + 8, blurb.iv, &des3res ); 255 memcpy( blurb.cipherbytes, des3res, 72 ); 256 257 blurb64 = base64_encode( (unsigned char*) &blurb, sizeof( blurb ) ); 258 msn_auth_got_passport_token( ic, blurb64 ); 259 260 g_free( padnonce ); 261 g_free( blurb64 ); 262 g_free( des3res ); 263 g_free( key1 ); 264 g_free( key2 ); 265 g_free( key3 ); 266 267 return MSN_SOAP_OK; 268 } 269 270 static int msn_soap_passport_sso_free_data( struct msn_soap_req_data *soap_req ) 271 { 272 struct msn_soap_passport_sso_data *sd = soap_req->data; 273 274 g_free( sd->policy ); 275 g_free( sd->nonce ); 276 g_free( sd->secret ); 277 278 return MSN_SOAP_OK; 279 } 280 281 int msn_soap_passport_sso_request( struct im_connection *ic, const char *policy, const char *nonce ) 282 { 283 struct msn_soap_passport_sso_data *sd = g_new0( struct msn_soap_passport_sso_data, 1 ); 284 285 sd->policy = g_strdup( policy ); 286 sd->nonce = g_strdup( nonce ); 287 288 return msn_soap_start( ic, sd, msn_soap_passport_sso_build_request, 289 msn_soap_passport_sso_parser, 290 msn_soap_passport_sso_handle_response, 291 msn_soap_passport_sso_free_data ); 292 } 293 294 142 295 /* oim_send: Sending offline messages */ 143 296 … … 162 315 soap_req->action = g_strdup( SOAP_OIM_SEND_ACTION ); 163 316 soap_req->payload = g_markup_printf_escaped( SOAP_OIM_SEND_PAYLOAD, 164 ic->acc->user, display_name_b64, oim->to, md->passport_token,317 ic->acc->user, display_name_b64, oim->to, "bla", //md->passport_token, 165 318 MSNP11_PROD_ID, md->lock_key ? md->lock_key : "", 166 319 oim->number, oim->number, oim->msg ); … … 168 321 g_free( display_name_b64 ); 169 322 170 return 1;323 return MSN_SOAP_OK; 171 324 } 172 325 … … 220 373 g_free( oim ); 221 374 222 return 0;375 return MSN_SOAP_OK; 223 376 } 224 377 … … 263 416 *msgq = g_slist_remove( *msgq, m ); 264 417 } 418 419 return 1; 265 420 } 266 421 -
protocols/msn/soap.h
r7db65b7 r523fb23 43 43 "Host: %s\r\n" \ 44 44 "Accept: */*\r\n" \ 45 "SOAPAction: \"%s\"\r\n" \46 45 "User-Agent: BitlBee " BITLBEE_VERSION "\r\n" \ 47 46 "Content-Type: text/xml; charset=utf-8\r\n" \ 48 " Cookie: MSPAuth=%s\r\n" \49 "Content-Length: % d\r\n" \47 "%s" \ 48 "Content-Length: %zd\r\n" \ 50 49 "Cache-Control: no-cache\r\n" \ 51 50 "\r\n" \ 52 51 "%s" 52 53 54 #define SOAP_PASSPORT_SSO_URL "https://login.live.com/RST.srf" 55 #define SOAP_PASSPORT_SSO_URL_MSN "https://msnia.login.live.com/pp550/RST.srf" 56 57 #define SOAP_PASSPORT_SSO_PAYLOAD \ 58 "<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\" " \ 59 "xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" " \ 60 "xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\" " \ 61 "xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\" " \ 62 "xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" " \ 63 "xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\" " \ 64 "xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\" " \ 65 "xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">" \ 66 "<Header>" \ 67 "<ps:AuthInfo " \ 68 "xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" " \ 69 "Id=\"PPAuthInfo\">" \ 70 "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>" \ 71 "<ps:BinaryVersion>4</ps:BinaryVersion>" \ 72 "<ps:UIVersion>1</ps:UIVersion>" \ 73 "<ps:Cookies></ps:Cookies>" \ 74 "<ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams>" \ 75 "</ps:AuthInfo>" \ 76 "<wsse:Security>" \ 77 "<wsse:UsernameToken Id=\"user\">" \ 78 "<wsse:Username>%s</wsse:Username>" \ 79 "<wsse:Password>%s</wsse:Password>" \ 80 "</wsse:UsernameToken>" \ 81 "</wsse:Security>" \ 82 "</Header>" \ 83 "<Body>" \ 84 "<ps:RequestMultipleSecurityTokens " \ 85 "xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" " \ 86 "Id=\"RSTS\">" \ 87 "<wst:RequestSecurityToken Id=\"RST0\">" \ 88 "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ 89 "<wsp:AppliesTo>" \ 90 "<wsa:EndpointReference>" \ 91 "<wsa:Address>http://Passport.NET/tb</wsa:Address>" \ 92 "</wsa:EndpointReference>" \ 93 "</wsp:AppliesTo>" \ 94 "</wst:RequestSecurityToken>" \ 95 "<wst:RequestSecurityToken Id=\"RST1\">" \ 96 "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ 97 "<wsp:AppliesTo>" \ 98 "<wsa:EndpointReference>" \ 99 "<wsa:Address>messengerclear.live.com</wsa:Address>" \ 100 "</wsa:EndpointReference>" \ 101 "</wsp:AppliesTo>" \ 102 "<wsse:PolicyReference URI=\"%s\"></wsse:PolicyReference>" \ 103 "</wst:RequestSecurityToken>" \ 104 "<wst:RequestSecurityToken Id=\"RST2\">" \ 105 "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>" \ 106 "<wsp:AppliesTo>" \ 107 "<wsa:EndpointReference>" \ 108 "<wsa:Address>contacts.msn.com</wsa:Address>" \ 109 "</wsa:EndpointReference>" \ 110 "</wsp:AppliesTo>" \ 111 "<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"MBI\"></wsse:PolicyReference>" \ 112 "</wst:RequestSecurityToken>" \ 113 "</ps:RequestMultipleSecurityTokens>" \ 114 "</Body>" \ 115 "</Envelope>" 116 117 int msn_soap_passport_sso_request( struct im_connection *ic, const char *policy, const char *nonce ); 53 118 54 119
Note: See TracChangeset
for help on using the changeset viewer.