Fix type errors in sip-sec-ntlm.c reported in forum
[siplcs.git] / src / sip-sec-ntlm.c
blob3b0f02d2616cca342e3aa30f06a2f4942c40ed88
1 /**
2 * @file sip-sec-ntlm.c
4 * pidgin-sipe
6 * Copyright (C) 2009 pier11 <pier11@operamail.com>
7 * Copyright (C) 2008 Novell, Inc.
8 * Modify 2007, Anibal Avelar <avelar@gmail.com>
9 * Copyright (C) 2005, Thomas Butter <butter@uni-mannheim.de>
11 * Implemented with reference to the follow documentation:
12 * - http://davenport.sourceforge.net/ntlm.html
13 * - MS-NLMP: http://msdn.microsoft.com/en-us/library/cc207842.aspx
14 * - MS-SIP : http://msdn.microsoft.com/en-us/library/cc246115.aspx
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include <glib.h>
32 #include <glib/gprintf.h>
33 #include <stdio.h>
34 #include <errno.h>
35 #include <string.h>
36 #include <stdlib.h>
37 #include "debug.h"
39 #ifndef _WIN32
40 #include <sys/socket.h>
41 #include <sys/ioctl.h>
42 #include <sys/types.h>
43 #include <netinet/in.h>
44 #include <net/if.h>
45 #else /* _WIN32 */
46 #include "libc_interface.h"
47 #ifdef _DLL
48 #define _WS2TCPIP_H_
49 #define _WINSOCK2API_
50 #define _LIBC_INTERNAL_
51 #endif /* _DLL */
52 #include "network.h"
53 #include "internal.h"
54 #endif /* _WIN32 */
56 #ifdef HAVE_LANGINFO_CODESET
57 #include <langinfo.h>
58 #endif /* HAVE_LANGINFO_CODESET */
60 #include "util.h"
61 #include "cipher.h"
63 #include "sipe.h"
64 #include "sipe-utils.h"
65 #include "sip-sec-mech.h"
66 #include "sip-sec-ntlm.h"
69 /***********************************************
71 * Start of merged code from original sip-ntlm.c
73 ***********************************************/
75 /* Negotiate flag required in connectionless NTLM
76 * 0x00000001 = NTLMSSP_NEGOTIATE_UNICODE (A)
77 * 0x00000010 = NTLMSSP_NEGOTIATE_SIGN (D)
78 * 0x00000040 = NTLMSSP_NEGOTIATE_DATAGRAM (F)
79 * 0x00000200 = NTLMSSP_NEGOTIATE_NTLM (H)
80 * 0x00008000 = NTLMSSP_NEGOTIATE_ALWAYS_SIGN (M)
81 * 0x40000000 = NTLMSSP_NEGOTIATE_KEY_EXCH (W)
83 #define NEGOTIATE_FLAGS 0x40008251
84 #define NTLM_NEGOTIATE_NTLM2_KEY 0x00080000
86 #define NTLMSSP_NT_OR_LM_KEY_LEN 24
87 #define NTLMSSP_SESSION_KEY_LEN 16
88 #define MD4_DIGEST_LEN 16
90 struct challenge_message {
91 guint8 protocol[8]; /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'*/
92 guint8 type; /* 0x02 */
93 guint8 zero1[7];
94 short msg_len; /* 0x28 */
95 guint8 zero2[2];
96 guint32 flags; /* 0x8201 */
98 guint8 nonce[8];
99 guint8 zero[8];
102 struct authenticate_message {
103 guint8 protocol[8]; /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'*/
104 //guint32 type; /* 0x03 */
105 guint8 type; /* 0x03 */
106 guint8 zero1[3];
108 guint16 lm_resp_len1; /* LanManager response length (always 0x18)*/
109 guint16 lm_resp_len2; /* LanManager response length (always 0x18)*/
110 //guint32 lm_resp_off; /* LanManager response offset */
111 guint16 lm_resp_off; /* LanManager response offset */
112 guint8 zero2[2];
114 /* NtChallengeResponseFields */
115 guint16 nt_resp_len1; /* NT response length (always 0x18) */
116 guint16 nt_resp_len2; /* NT response length (always 0x18) */
117 //guint32 nt_resp_off; /* NT response offset */
118 guint16 nt_resp_off; /* NT response offset */
119 guint8 zero3[2];
121 /* DomainNameFields */
122 guint16 dom_len1; /* domain string length */
123 guint16 dom_len2; /* domain string length */
124 //guint32 dom_off; /* domain string offset (always 0x40) */
125 guint16 dom_off; /* domain string offset (always 0x40) */
126 guint8 zero4[2];
128 /* UserNameFields */
129 guint16 user_len1; /* username string length */
130 guint16 user_len2; /* username string length */
131 //guint32 user_off; /* username string offset */
132 guint16 user_off; /* username string offset */
133 guint8 zero5[2];
135 /* WorkstationFields */
136 guint16 host_len1; /* host string length */
137 guint16 host_len2; /* host string length */
138 //guint32 host_off; /* host string offset */
139 guint16 host_off; /* host string offset */
140 guint8 zero6[2];
142 /* EncryptedRandomSessionKeyFields */
143 guint16 sess_len1;
144 guint16 sess_len2;
145 //guint32 sess_off;
146 guint16 sess_off;
147 guint8 zero7[2];
149 guint32 flags;
151 // don't care values
152 // version
153 // mic
155 // payload
156 /* guint32 flags2; unknown, used in windows messenger
157 guint32 flags3; */
159 #if 0
160 guint8 dom[*]; /* domain string (unicode UTF-16LE) */
161 guint8 user[*]; /* username string (unicode UTF-16LE) */
162 guint8 host[*]; /* host string (unicode UTF-16LE) */
163 guint8 lm_resp[*]; /* LanManager response */
164 guint8 nt_resp[*]; /* NT response */
165 #endif
168 #ifndef HAVE_LANGINFO_CODESET
169 static char SIPE_DEFAULT_CODESET[] = "ANSI_X3.4-1968";
170 #endif
172 /* Private Methods */
174 static void setup_des_key(const unsigned char key_56[], unsigned char *key)
176 key[0] = key_56[0];
177 key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
178 key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
179 key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
180 key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
181 key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
182 key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
183 key[7] = (key_56[6] << 1) & 0xFF;
186 static void des_ecb_encrypt(const unsigned char *plaintext, unsigned char *result, const unsigned char *key)
188 PurpleCipher *cipher;
189 PurpleCipherContext *context;
190 size_t outlen;
192 cipher = purple_ciphers_find_cipher("des");
193 context = purple_cipher_context_new(cipher, NULL);
194 purple_cipher_context_set_key(context, (guchar*)key);
195 purple_cipher_context_encrypt(context, (guchar*)plaintext, 8, (guchar*)result, &outlen);
196 purple_cipher_context_destroy(context);
199 static int
200 unicode_strconvcopy(gchar *dest, const gchar *source, int remlen)
202 GIConv fd;
203 gchar *inbuf = (gchar *) source;
204 gchar *outbuf = dest;
205 gsize inbytes = strlen(source);
206 gsize outbytes = remlen;
207 #ifdef HAVE_LANGINFO_CODESET
208 char *sys_cp = nl_langinfo(CODESET);
209 #else
210 char *sys_cp = SIPE_DEFAULT_CODESET;
211 #endif /* HAVE_LANGINFO_CODESET */
213 /* fall back to utf-8 */
214 if (!sys_cp) sys_cp = "UTF-8";
216 fd = g_iconv_open("UTF-16LE", sys_cp);
217 if( fd == (GIConv)-1 ) {
218 purple_debug_error( "sipe", "iconv_open returned -1, cannot continue\n" );
220 g_iconv(fd, &inbuf, &inbytes, &outbuf, &outbytes);
221 g_iconv_close(fd);
222 return (remlen - outbytes);
225 // (k = 7 byte key, d = 8 byte data) returns 8 bytes in results
226 static void
227 DES (const unsigned char *k, const unsigned char *d, unsigned char * results)
229 unsigned char key[8];
230 setup_des_key(k, key);
231 des_ecb_encrypt(d, results, key);
234 // (K = 21 byte key, D = 8 bytes of data) returns 24 bytes in results:
235 static void
236 DESL (unsigned char *k, const unsigned char *d, unsigned char * results)
238 unsigned char keys[21];
240 // Copy the first 16 bytes
241 memcpy(keys, k, 16);
243 // Zero out the last 5 bytes of the key
244 memset(keys + 16, 0, 5);
246 DES(keys, d, results);
247 DES(keys + 7, d, results + 8);
248 DES(keys + 14, d, results + 16);
251 static void
252 MD4 (const unsigned char * d, int len, unsigned char * result)
254 PurpleCipher * cipher = purple_ciphers_find_cipher("md4");
255 PurpleCipherContext * context = purple_cipher_context_new(cipher, NULL);
256 purple_cipher_context_append(context, (guchar*)d, len);
257 purple_cipher_context_digest(context, MD4_DIGEST_LEN, (guchar*)result, NULL);
258 purple_cipher_context_destroy(context);
262 static void
263 NTOWFv1 (const char* password, SIPE_UNUSED_PARAMETER const char *user, SIPE_UNUSED_PARAMETER const char *domain, unsigned char * result)
265 int len = 2 * strlen(password); // utf16 should not be more
266 unsigned char *unicode_password = g_new0(unsigned char, len);
268 len = unicode_strconvcopy((gchar *) unicode_password, password, len);
269 MD4 (unicode_password, len, result);
270 g_free(unicode_password);
273 // static void
274 // MD5 (const char * d, int len, char * result)
275 // {
276 // PurpleCipher * cipher = purple_ciphers_find_cipher("md5");
277 // PurpleCipherContext * context = purple_cipher_context_new(cipher, NULL);
278 // purple_cipher_context_append(context, (guchar*)d, len);
279 // purple_cipher_context_digest(context, len, (guchar*)result, NULL);
280 // purple_cipher_context_destroy(context);
281 // }
283 static void
284 RC4K (const unsigned char * k, const unsigned char * d, unsigned char * result)
286 PurpleCipherContext * context = purple_cipher_context_new_by_name("rc4", NULL);
287 purple_cipher_context_set_option(context, "key_len", (gpointer)16);
288 purple_cipher_context_set_key(context, k);
289 purple_cipher_context_encrypt(context, (const guchar *)d, 16, result, NULL);
290 purple_cipher_context_destroy(context);
293 static void
294 KXKEY (const unsigned char * session_base_key, SIPE_UNUSED_PARAMETER const unsigned char * lm_challenge_resonse, unsigned char * key_exchange_key)
296 // Assume v1 and NTLMSSP_REQUEST_NON_NT_SESSION_KEY not set
297 memcpy(key_exchange_key, session_base_key, 16);
300 // This method is only used for NTLM v2 session security w/ enhanced security negotiated
301 /*void
302 SIGNKEY (const char * random_session_key, gboolean client, char * result)
304 char * magic = client
305 ? "session key to client-to-server signing key magic constant"
306 : "session key to server-to-client signing key magic constant";
308 int len = strlen(magic);
309 char md5_input [16 + len];
310 memcpy(md5_input, random_session_key, 16);
311 memcpy(md5_input + 16, magic, len);
313 MD5 (md5_input, len + 16, result);
316 static void
317 LMOWFv1 (const char *password, SIPE_UNUSED_PARAMETER const char *user, SIPE_UNUSED_PARAMETER const char *domain, unsigned char *result)
319 /* "KGS!@#$%" */
320 unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
321 unsigned char uppercase_password[14];
322 int i;
324 int len = strlen(password);
325 if (len > 14) {
326 len = 14;
329 // Uppercase password
330 for (i = 0; i < len; i++) {
331 uppercase_password[i] = g_ascii_toupper(password[i]);
334 // Zero the rest
335 for (; i < 14; i++) {
336 uppercase_password[i] = 0;
339 DES (uppercase_password, magic, result);
340 DES (uppercase_password + 7, magic, result + 8);
343 static void
344 NONCE(unsigned char *buffer, int num)
346 int i;
347 for (i = 0; i < num; i++) {
348 buffer[i] = (rand() & 0xff);
352 /* End Private Methods */
354 static gchar *purple_ntlm_parse_challenge(const char *challenge, guint32 *flags) {
355 gsize retlen;
356 static gchar nonce[8];
357 struct challenge_message *tmsg = (struct challenge_message*)purple_base64_decode(challenge, &retlen);
358 memcpy(nonce, tmsg->nonce, 8);
360 purple_debug_info("sipe", "received NTLM NegotiateFlags = %X; OK? %i\n", tmsg->flags, (tmsg->flags & NEGOTIATE_FLAGS) == NEGOTIATE_FLAGS);
362 if (flags) {
363 *flags = tmsg->flags;
365 g_free(tmsg);
366 return nonce;
369 // static void
370 // print_hex_array(char * msg, int num)
371 // {
372 // int k;
373 // for (k = 0; k < num; k++) {
374 // printf("0x%02X, ", msg[k]&0xff);
375 // }
376 // printf("\n");
377 // }
379 // static void
380 // print_hex_array_title(char * title, char * msg, int num)
381 // {
382 // printf("%s:\n", title);
383 // print_hex_array(msg, num);
384 // }
386 /* source copy from gg's common.c */
387 static guint32 crc32_table[256];
388 static int crc32_initialized = 0;
390 static void crc32_make_table()
392 guint32 h = 1;
393 unsigned int i, j;
395 memset(crc32_table, 0, sizeof(crc32_table));
397 for (i = 128; i; i >>= 1) {
398 h = (h >> 1) ^ ((h & 1) ? 0xedb88320L : 0);
400 for (j = 0; j < 256; j += 2 * i)
401 crc32_table[i + j] = crc32_table[j] ^ h;
404 crc32_initialized = 1;
407 static guint32 crc32(guint32 crc, const guint8 *buf, int len)
409 if (!crc32_initialized)
410 crc32_make_table();
412 if (!buf || len < 0)
413 return crc;
415 crc ^= 0xffffffffL;
417 while (len--)
418 crc = (crc >> 8) ^ crc32_table[(crc ^ *buf++) & 0xff];
420 return crc ^ 0xffffffffL;
423 static guint32
424 CRC32 (const char * msg)
426 guint32 crc = 0L;//crc32(0L, Z_NULL, 0);
427 crc = crc32(crc, (guint8 *) msg, strlen(msg));
428 //char * ptr = (char*) &crc;
429 //return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | (ptr[3] & 0xff);
430 return crc;
433 static gchar *
434 purple_ntlm_gen_signature (const char * buf, unsigned char * signing_key, guint32 random_pad, long sequence, int key_len)
436 gint32 *res_ptr;
437 gint32 plaintext [] = {0, CRC32(buf), sequence};
439 guchar result [16];
440 gchar signature [33];
441 int i, j;
442 PurpleCipherContext *rc4 = purple_cipher_context_new_by_name("rc4", NULL);
443 purple_cipher_context_set_option(rc4, "key_len", (gpointer) key_len);
445 purple_cipher_context_set_key(rc4, signing_key);
446 purple_cipher_context_encrypt(rc4, (const guchar *)plaintext, 12, result+4, NULL);
447 purple_cipher_context_destroy(rc4);
449 res_ptr = (gint32 *)result;
450 // Highest four bytes are the Version
451 res_ptr[0] = 0x00000001;
453 // Replace the first four bytes of the ciphertext with a counter value
454 // currently set to this hardcoded value
455 res_ptr[1] = random_pad;
457 for (i = 0, j = 0; i < 16; i++, j+=2) {
458 g_sprintf(&signature[j], "%02X", result[i]);
461 //printf("sig: %s\n", signature);
462 return g_strdup(signature);
465 static gchar *
466 purple_ntlm_sipe_signature_make (const char * msg, unsigned char * signing_key)
468 return purple_ntlm_gen_signature(msg, signing_key, 0, 100, 16);
471 static gboolean
472 purple_ntlm_verify_signature (char * a, char * b)
474 // Make sure the last 16 bytes match
475 gboolean ret = g_ascii_strncasecmp(a + 16, b + 16, 16) == 0;
476 return ret;
479 static gchar *
480 purple_ntlm_gen_authenticate(guchar **ntlm_key, const gchar *user, const gchar *password, const gchar *hostname, const gchar *domain, const guint8 *nonce, SIPE_UNUSED_PARAMETER guint32 *flags)
482 int msglen = sizeof(struct authenticate_message) + 2*(strlen(domain)
483 + strlen(user)+ strlen(hostname) + NTLMSSP_NT_OR_LM_KEY_LEN)
484 + NTLMSSP_SESSION_KEY_LEN;
485 struct authenticate_message *tmsg = g_malloc0(msglen);
486 char *tmp;
487 int remlen;
488 unsigned char response_key_lm [16];
489 unsigned char lm_challenge_response [NTLMSSP_NT_OR_LM_KEY_LEN];
490 unsigned char response_key_nt [16];
491 unsigned char nt_challenge_response [NTLMSSP_NT_OR_LM_KEY_LEN];
492 unsigned char session_base_key [16];
493 unsigned char key_exchange_key [16];
494 unsigned char exported_session_key[16];
495 unsigned char encrypted_random_session_key [16];
497 /* authenticate message initialization */
498 memcpy(tmsg->protocol, "NTLMSSP\0", 8);
499 tmsg->type = 3;
501 /* Set Negotiate Flags */
502 tmsg->flags = NEGOTIATE_FLAGS;
504 /* Domain */
505 tmsg->dom_off = sizeof(struct authenticate_message);
506 tmp = ((char*) tmsg) + sizeof(struct authenticate_message);
507 remlen = ((char *)tmsg)+msglen-tmp;
508 tmsg->dom_len1 = tmsg->dom_len2 = unicode_strconvcopy(tmp, domain, remlen);
509 tmp += tmsg->dom_len1;
510 remlen = ((char *)tmsg)+msglen-tmp;
512 /* User */
513 tmsg->user_off = tmsg->dom_off + tmsg->dom_len1;
514 tmsg->user_len1 = tmsg->user_len2 = unicode_strconvcopy(tmp, user, remlen);
515 tmp += tmsg->user_len1;
516 remlen = ((char *)tmsg)+msglen-tmp;
518 /* Host */
519 tmsg->host_off = tmsg->user_off + tmsg->user_len1;
520 tmsg->host_len1 = tmsg->host_len2 = unicode_strconvcopy(tmp, hostname, remlen);
521 tmp += tmsg->host_len1;
523 /* LM */
524 tmsg->lm_resp_len1 = tmsg->lm_resp_len2 = NTLMSSP_NT_OR_LM_KEY_LEN;
525 tmsg->lm_resp_off = tmsg->host_off + tmsg->host_len1;
527 LMOWFv1 (password, user, domain, response_key_lm);
528 DESL (response_key_lm, nonce, lm_challenge_response);
529 memcpy(tmp, lm_challenge_response, NTLMSSP_NT_OR_LM_KEY_LEN);
530 tmp += NTLMSSP_NT_OR_LM_KEY_LEN;
532 /* NT */
533 tmsg->nt_resp_len1 = tmsg->nt_resp_len2 = NTLMSSP_NT_OR_LM_KEY_LEN;
534 tmsg->nt_resp_off = tmsg->lm_resp_off + tmsg->lm_resp_len1;
536 NTOWFv1 (password, user, domain, response_key_nt);
537 DESL (response_key_nt, nonce, nt_challenge_response);
538 memcpy(tmp, nt_challenge_response, NTLMSSP_NT_OR_LM_KEY_LEN);
539 tmp += NTLMSSP_NT_OR_LM_KEY_LEN;
541 /* Session Key */
542 tmsg->sess_len1 = tmsg->sess_len2 = NTLMSSP_SESSION_KEY_LEN;
543 tmsg->sess_off = tmsg->nt_resp_off + tmsg->nt_resp_len1;
545 MD4(response_key_nt, 16, session_base_key);
547 KXKEY(session_base_key, lm_challenge_response, key_exchange_key);
549 NONCE (exported_session_key, 16);
551 *ntlm_key = (guchar *) g_strndup ((gchar *) exported_session_key, 16);
553 RC4K (key_exchange_key, exported_session_key, encrypted_random_session_key);
554 memcpy(tmp, encrypted_random_session_key, 16);
555 tmp += NTLMSSP_SESSION_KEY_LEN;
557 tmp = purple_base64_encode(exported_session_key, 16);
558 purple_debug_info("sipe", "Generated NTLM AUTHENTICATE message (%s)\n", tmp);
559 g_free(tmp);
561 tmp = purple_base64_encode((guchar*) tmsg, msglen);
562 g_free(tmsg);
563 return tmp;
566 /***********************************************
568 * End of merged code from original sip-ntlm.c
570 ***********************************************/
572 /* sip-sec-mech.h API implementation for NTLM */
574 /* Security context for NTLM */
575 typedef struct _context_ntlm {
576 struct sip_sec_context common;
577 char* domain;
578 char *username;
579 char *password;
580 int step;
581 guchar *key;
582 } *context_ntlm;
585 static sip_uint32
586 sip_sec_acquire_cred__ntlm(SipSecContext context,
587 const char *domain,
588 const char *username,
589 const char *password)
591 context_ntlm ctx = (context_ntlm)context;
593 /* NTLM requires a password */
594 if (!password) return SIP_SEC_E_INTERNAL_ERROR;
596 ctx->domain = g_strdup(domain);
597 ctx->username = g_strdup(username);
598 ctx->password = g_strdup(password);
600 return SIP_SEC_E_OK;
603 static sip_uint32
604 sip_sec_init_sec_context__ntlm(SipSecContext context,
605 SipSecBuffer in_buff,
606 SipSecBuffer *out_buff,
607 SIPE_UNUSED_PARAMETER const char *service_name)
609 context_ntlm ctx = (context_ntlm) context;
611 purple_debug_info("sipe", "sip_sec_init_sec_context__ntlm: in use\n");
613 ctx->step++;
614 if (ctx->step == 1) {
615 out_buff->length = 0;
616 out_buff->value = NULL;
617 // same behaviour as sspi
618 return SIP_SEC_I_CONTINUE_NEEDED;
620 } else {
621 guchar *ntlm_key;
622 guchar *nonce;
623 guint32 flags;
624 gchar *input_toked_base64;
625 gchar *gssapi_data;
627 input_toked_base64 = purple_base64_encode(in_buff.value,
628 in_buff.length);
630 nonce = g_memdup(purple_ntlm_parse_challenge(input_toked_base64, &flags), 8);
631 g_free(input_toked_base64);
633 gssapi_data = purple_ntlm_gen_authenticate(&ntlm_key,
634 ctx->username,
635 ctx->password,
636 sipe_get_host_name(),
637 ctx->domain,
638 nonce,
639 &flags);
640 g_free(nonce);
642 out_buff->value = purple_base64_decode(gssapi_data, &(out_buff->length));
643 g_free(gssapi_data);
645 g_free(ctx->key);
646 ctx->key = ntlm_key;
647 return SIP_SEC_E_OK;
652 * @param message a NULL terminated string to sign
655 static sip_uint32
656 sip_sec_make_signature__ntlm(SipSecContext context,
657 const char *message,
658 SipSecBuffer *signature)
660 gchar *signature_hex = purple_ntlm_sipe_signature_make(message,
661 ((context_ntlm) context)->key);
663 hex_str_to_bytes(signature_hex, signature);
664 g_free(signature_hex);
666 return SIP_SEC_E_OK;
670 * @param message a NULL terminated string to check signature of
671 * @return SIP_SEC_E_OK on success
673 static sip_uint32
674 sip_sec_verify_signature__ntlm(SipSecContext context,
675 const char *message,
676 SipSecBuffer signature)
678 char *signature_hex = bytes_to_hex_str(&signature);
679 gchar *signature_calc = purple_ntlm_sipe_signature_make(message,
680 ((context_ntlm) context)->key);
681 sip_uint32 res;
683 if (purple_ntlm_verify_signature(signature_calc, signature_hex)) {
684 res = SIP_SEC_E_OK;
685 } else {
686 res = SIP_SEC_E_INTERNAL_ERROR;
688 g_free(signature_calc);
689 g_free(signature_hex);
690 return(res);
693 static void
694 sip_sec_destroy_sec_context__ntlm(SipSecContext context)
696 context_ntlm ctx = (context_ntlm) context;
698 g_free(ctx->domain);
699 g_free(ctx->username);
700 g_free(ctx->password);
701 g_free(ctx->key);
702 g_free(ctx);
705 SipSecContext
706 sip_sec_create_context__ntlm(SIPE_UNUSED_PARAMETER SipSecAuthType type)
708 context_ntlm context = g_malloc0(sizeof(struct _context_ntlm));
709 if (!context) return(NULL);
711 context->common.acquire_cred_func = sip_sec_acquire_cred__ntlm;
712 context->common.init_context_func = sip_sec_init_sec_context__ntlm;
713 context->common.destroy_context_func = sip_sec_destroy_sec_context__ntlm;
714 context->common.make_signature_func = sip_sec_make_signature__ntlm;
715 context->common.verify_signature_func = sip_sec_verify_signature__ntlm;
717 return((SipSecContext) context);
722 Local Variables:
723 mode: c
724 c-file-style: "bsd"
725 indent-tabs-mode: t
726 tab-width: 8
727 End: