Move the hardcode debug flags from src/Makefile.am file to configure.ac file.
[siplcs.git] / src / sip-sec-ntlm.c
blobfaac68b5ee624de92c3af644ba0cb4a5627b0f4e
1 /**
2 * @file sip-sec-ntlm.c
4 * pidgin-sipe
6 * Copyright (C) 2009 pier11 <pier11@kinozal.tv>
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 "sip-sec.h"
64 #include "sip-sec-mech.h"
65 #include "sip-sec-ntlm.h"
68 /***********************************************
70 * Start of merged code from original sip-ntlm.c
72 ***********************************************/
74 /* Negotiate flag required in connectionless NTLM
75 * 0x00000001 = NTLMSSP_NEGOTIATE_UNICODE (A)
76 * 0x00000010 = NTLMSSP_NEGOTIATE_SIGN (D)
77 * 0x00000040 = NTLMSSP_NEGOTIATE_DATAGRAM (F)
78 * 0x00000200 = NTLMSSP_NEGOTIATE_NTLM (H)
79 * 0x00008000 = NTLMSSP_NEGOTIATE_ALWAYS_SIGN (M)
80 * 0x40000000 = NTLMSSP_NEGOTIATE_KEY_EXCH (W)
82 #define NEGOTIATE_FLAGS 0x40008251
83 #define NTLM_NEGOTIATE_NTLM2_KEY 0x00080000
85 #define NTLMSSP_NT_OR_LM_KEY_LEN 24
86 #define NTLMSSP_SESSION_KEY_LEN 16
87 #define MD4_DIGEST_LEN 16
89 struct challenge_message {
90 guint8 protocol[8]; /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'*/
91 guint8 type; /* 0x02 */
92 guint8 zero1[7];
93 short msg_len; /* 0x28 */
94 guint8 zero2[2];
95 guint32 flags; /* 0x8201 */
97 guint8 nonce[8];
98 guint8 zero[8];
101 struct authenticate_message {
102 guint8 protocol[8]; /* 'N', 'T', 'L', 'M', 'S', 'S', 'P', '\0'*/
103 //guint32 type; /* 0x03 */
104 guint8 type; /* 0x03 */
105 guint8 zero1[3];
107 guint16 lm_resp_len1; /* LanManager response length (always 0x18)*/
108 guint16 lm_resp_len2; /* LanManager response length (always 0x18)*/
109 //guint32 lm_resp_off; /* LanManager response offset */
110 guint16 lm_resp_off; /* LanManager response offset */
111 guint8 zero2[2];
113 /* NtChallengeResponseFields */
114 guint16 nt_resp_len1; /* NT response length (always 0x18) */
115 guint16 nt_resp_len2; /* NT response length (always 0x18) */
116 //guint32 nt_resp_off; /* NT response offset */
117 guint16 nt_resp_off; /* NT response offset */
118 guint8 zero3[2];
120 /* DomainNameFields */
121 guint16 dom_len1; /* domain string length */
122 guint16 dom_len2; /* domain string length */
123 //guint32 dom_off; /* domain string offset (always 0x40) */
124 guint16 dom_off; /* domain string offset (always 0x40) */
125 guint8 zero4[2];
127 /* UserNameFields */
128 guint16 user_len1; /* username string length */
129 guint16 user_len2; /* username string length */
130 //guint32 user_off; /* username string offset */
131 guint16 user_off; /* username string offset */
132 guint8 zero5[2];
134 /* WorkstationFields */
135 guint16 host_len1; /* host string length */
136 guint16 host_len2; /* host string length */
137 //guint32 host_off; /* host string offset */
138 guint16 host_off; /* host string offset */
139 guint8 zero6[2];
141 /* EncryptedRandomSessionKeyFields */
142 guint16 sess_len1;
143 guint16 sess_len2;
144 //guint32 sess_off;
145 guint16 sess_off;
146 guint8 zero7[2];
148 guint32 flags;
150 // don't care values
151 // version
152 // mic
154 // payload
155 /* guint32 flags2; unknown, used in windows messenger
156 guint32 flags3; */
158 #if 0
159 guint8 dom[*]; /* domain string (unicode UTF-16LE) */
160 guint8 user[*]; /* username string (unicode UTF-16LE) */
161 guint8 host[*]; /* host string (unicode UTF-16LE) */
162 guint8 lm_resp[*]; /* LanManager response */
163 guint8 nt_resp[*]; /* NT response */
164 #endif
167 #ifndef HAVE_LANGINFO_CODESET
168 static char SIPE_DEFAULT_CODESET[] = "ANSI_X3.4-1968";
169 #endif
171 /* Private Methods */
173 static void setup_des_key(const unsigned char key_56[], unsigned char *key)
175 key[0] = key_56[0];
176 key[1] = ((key_56[0] << 7) & 0xFF) | (key_56[1] >> 1);
177 key[2] = ((key_56[1] << 6) & 0xFF) | (key_56[2] >> 2);
178 key[3] = ((key_56[2] << 5) & 0xFF) | (key_56[3] >> 3);
179 key[4] = ((key_56[3] << 4) & 0xFF) | (key_56[4] >> 4);
180 key[5] = ((key_56[4] << 3) & 0xFF) | (key_56[5] >> 5);
181 key[6] = ((key_56[5] << 2) & 0xFF) | (key_56[6] >> 6);
182 key[7] = (key_56[6] << 1) & 0xFF;
185 static void des_ecb_encrypt(const unsigned char *plaintext, unsigned char *result, const unsigned char *key)
187 PurpleCipher *cipher;
188 PurpleCipherContext *context;
189 gsize outlen;
191 cipher = purple_ciphers_find_cipher("des");
192 context = purple_cipher_context_new(cipher, NULL);
193 purple_cipher_context_set_key(context, (guchar*)key);
194 purple_cipher_context_encrypt(context, (guchar*)plaintext, 8, (guchar*)result, &outlen);
195 purple_cipher_context_destroy(context);
198 static int
199 unicode_strconvcopy(gchar *dest, const gchar *source, int remlen)
201 GIConv fd;
202 gchar *inbuf = (gchar *) source;
203 gchar *outbuf = dest;
204 size_t inbytes = strlen(source);
205 size_t outbytes = remlen;
206 #ifdef HAVE_LANGINFO_CODESET
207 char *sys_cp = nl_langinfo(CODESET);
208 #else
209 char *sys_cp = SIPE_DEFAULT_CODESET;
210 #endif /* HAVE_LANGINFO_CODESET */
212 /* fall back to utf-8 */
213 if (!sys_cp) sys_cp = "UTF-8";
215 fd = g_iconv_open("UTF-16LE", sys_cp);
216 if( fd == (GIConv)-1 ) {
217 purple_debug_error( "sipe", "iconv_open returned -1, cannot continue\n" );
219 g_iconv(fd, &inbuf, &inbytes, &outbuf, &outbytes);
220 g_iconv_close(fd);
221 return (remlen - outbytes);
224 // (k = 7 byte key, d = 8 byte data) returns 8 bytes in results
225 static void
226 DES (const unsigned char *k, const unsigned char *d, unsigned char * results)
228 unsigned char key[8];
229 setup_des_key(k, key);
230 des_ecb_encrypt(d, results, key);
233 // (K = 21 byte key, D = 8 bytes of data) returns 24 bytes in results:
234 static void
235 DESL (unsigned char *k, const unsigned char *d, unsigned char * results)
237 unsigned char keys[21];
239 // Copy the first 16 bytes
240 memcpy(keys, k, 16);
242 // Zero out the last 5 bytes of the key
243 memset(keys + 16, 0, 5);
245 DES(keys, d, results);
246 DES(keys + 7, d, results + 8);
247 DES(keys + 14, d, results + 16);
250 static void
251 MD4 (const unsigned char * d, int len, unsigned char * result)
253 PurpleCipher * cipher = purple_ciphers_find_cipher("md4");
254 PurpleCipherContext * context = purple_cipher_context_new(cipher, NULL);
255 purple_cipher_context_append(context, (guchar*)d, len);
256 purple_cipher_context_digest(context, MD4_DIGEST_LEN, (guchar*)result, NULL);
257 purple_cipher_context_destroy(context);
261 static void
262 NTOWFv1 (const char* password, const char *user, const char *domain, unsigned char * result)
264 int len = 2 * strlen(password); // utf16 should not be more
265 unsigned char *unicode_password = g_new0(unsigned char, len);
267 len = unicode_strconvcopy((gchar *) unicode_password, password, len);
268 MD4 (unicode_password, len, result);
269 g_free(unicode_password);
272 // static void
273 // MD5 (const char * d, int len, char * result)
274 // {
275 // PurpleCipher * cipher = purple_ciphers_find_cipher("md5");
276 // PurpleCipherContext * context = purple_cipher_context_new(cipher, NULL);
277 // purple_cipher_context_append(context, (guchar*)d, len);
278 // purple_cipher_context_digest(context, len, (guchar*)result, NULL);
279 // purple_cipher_context_destroy(context);
280 // }
282 static void
283 RC4K (const unsigned char * k, const unsigned char * d, unsigned char * result)
285 PurpleCipherContext * context = purple_cipher_context_new_by_name("rc4", NULL);
286 purple_cipher_context_set_option(context, "key_len", (gpointer)16);
287 purple_cipher_context_set_key(context, k);
288 purple_cipher_context_encrypt(context, (const guchar *)d, 16, result, NULL);
289 purple_cipher_context_destroy(context);
292 static void
293 KXKEY (const unsigned char * session_base_key, const unsigned char * lm_challenge_resonse, unsigned char * key_exchange_key)
295 // Assume v1 and NTLMSSP_REQUEST_NON_NT_SESSION_KEY not set
296 memcpy(key_exchange_key, session_base_key, 16);
299 // This method is only used for NTLM v2 session security w/ enhanced security negotiated
300 /*void
301 SIGNKEY (const char * random_session_key, gboolean client, char * result)
303 char * magic = client
304 ? "session key to client-to-server signing key magic constant"
305 : "session key to server-to-client signing key magic constant";
307 int len = strlen(magic);
308 char md5_input [16 + len];
309 memcpy(md5_input, random_session_key, 16);
310 memcpy(md5_input + 16, magic, len);
312 MD5 (md5_input, len + 16, result);
315 static void
316 LMOWFv1 (const char *password, const char *user, const char *domain, unsigned char *result)
318 /* "KGS!@#$%" */
319 unsigned char magic[] = { 0x4B, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25 };
320 unsigned char uppercase_password[14];
321 int i;
323 int len = strlen(password);
324 if (len > 14) {
325 len = 14;
328 // Uppercase password
329 for (i = 0; i < len; i++) {
330 uppercase_password[i] = g_ascii_toupper(password[i]);
333 // Zero the rest
334 for (; i < 14; i++) {
335 uppercase_password[i] = 0;
338 DES (uppercase_password, magic, result);
339 DES (uppercase_password + 7, magic, result + 8);
342 static void
343 NONCE(unsigned char *buffer, int num)
345 int i;
346 for (i = 0; i < num; i++) {
347 buffer[i] = (rand() & 0xff);
351 /* End Private Methods */
353 static gchar *purple_ntlm_parse_challenge(const char *challenge, guint32 *flags) {
354 gsize retlen;
355 static gchar nonce[8];
356 struct challenge_message *tmsg = (struct challenge_message*)purple_base64_decode(challenge, &retlen);
357 memcpy(nonce, tmsg->nonce, 8);
359 purple_debug_info("sipe", "received NTLM NegotiateFlags = %X; OK? %i\n", tmsg->flags, (tmsg->flags & NEGOTIATE_FLAGS) == NEGOTIATE_FLAGS);
361 if (flags) {
362 *flags = tmsg->flags;
364 g_free(tmsg);
365 return nonce;
368 // static void
369 // print_hex_array(char * msg, int num)
370 // {
371 // int k;
372 // for (k = 0; k < num; k++) {
373 // printf("0x%02X, ", msg[k]&0xff);
374 // }
375 // printf("\n");
376 // }
378 // static void
379 // print_hex_array_title(char * title, char * msg, int num)
380 // {
381 // printf("%s:\n", title);
382 // print_hex_array(msg, num);
383 // }
385 /* source copy from gg's common.c */
386 static guint32 crc32_table[256];
387 static int crc32_initialized = 0;
389 static void crc32_make_table()
391 guint32 h = 1;
392 unsigned int i, j;
394 memset(crc32_table, 0, sizeof(crc32_table));
396 for (i = 128; i; i >>= 1) {
397 h = (h >> 1) ^ ((h & 1) ? 0xedb88320L : 0);
399 for (j = 0; j < 256; j += 2 * i)
400 crc32_table[i + j] = crc32_table[j] ^ h;
403 crc32_initialized = 1;
406 static guint32 crc32(guint32 crc, const guint8 *buf, int len)
408 if (!crc32_initialized)
409 crc32_make_table();
411 if (!buf || len < 0)
412 return crc;
414 crc ^= 0xffffffffL;
416 while (len--)
417 crc = (crc >> 8) ^ crc32_table[(crc ^ *buf++) & 0xff];
419 return crc ^ 0xffffffffL;
422 static guint32
423 CRC32 (const char * msg)
425 guint32 crc = 0L;//crc32(0L, Z_NULL, 0);
426 crc = crc32(crc, (guint8 *) msg, strlen(msg));
427 //char * ptr = (char*) &crc;
428 //return ptr[0] << 24 | ptr[1] << 16 | ptr[2] << 8 | (ptr[3] & 0xff);
429 return crc;
432 static gchar *
433 purple_ntlm_gen_signature (const char * buf, unsigned char * signing_key, guint32 random_pad, long sequence, int key_len)
435 gint32 *res_ptr;
436 gint32 plaintext [] = {0, CRC32(buf), sequence};
438 guchar result [16];
439 gchar signature [32];
440 int i, j;
441 PurpleCipherContext *rc4 = purple_cipher_context_new_by_name("rc4", NULL);
442 purple_cipher_context_set_option(rc4,"key_len", GINT_TO_POINTER(key_len));
444 purple_cipher_context_set_key(rc4, signing_key);
445 purple_cipher_context_encrypt(rc4, (const guchar *)plaintext, 12, result+4, NULL);
446 purple_cipher_context_destroy(rc4);
448 res_ptr = (gint32 *)result;
449 // Highest four bytes are the Version
450 res_ptr[0] = 0x00000001;
452 // Replace the first four bytes of the ciphertext with a counter value
453 // currently set to this hardcoded value
454 res_ptr[1] = random_pad;
456 for (i = 0, j = 0; i < 16; i++, j+=2) {
457 g_sprintf(&signature[j], "%02X", result[i]);
460 //printf("sig: %s\n", signature);
461 return g_strdup(signature);
464 static gchar *
465 purple_ntlm_sipe_signature_make (const char * msg, unsigned char * signing_key)
467 return purple_ntlm_gen_signature(msg, signing_key, 0, 100, 16);
470 static gboolean
471 purple_ntlm_verify_signature (char * a, char * b)
473 // Make sure the last 16 bytes match
474 gboolean ret = g_ascii_strncasecmp(a + 16, b + 16, 16) == 0;
475 return ret;
478 static gchar *
479 purple_ntlm_gen_authenticate(guchar **ntlm_key, const gchar *user, const gchar *password, const gchar *hostname, const gchar *domain, const guint8 *nonce, guint32 *flags)
481 int msglen = sizeof(struct authenticate_message) + 2*(strlen(domain)
482 + strlen(user)+ strlen(hostname) + NTLMSSP_NT_OR_LM_KEY_LEN)
483 + NTLMSSP_SESSION_KEY_LEN;
484 struct authenticate_message *tmsg = g_malloc0(msglen);
485 char *tmp;
486 int remlen;
487 unsigned char response_key_lm [16];
488 unsigned char lm_challenge_response [NTLMSSP_NT_OR_LM_KEY_LEN];
489 unsigned char response_key_nt [16];
490 unsigned char nt_challenge_response [NTLMSSP_NT_OR_LM_KEY_LEN];
491 unsigned char session_base_key [16];
492 unsigned char key_exchange_key [16];
493 unsigned char exported_session_key[16];
494 unsigned char encrypted_random_session_key [16];
496 /* authenticate message initialization */
497 memcpy(tmsg->protocol, "NTLMSSP\0", 8);
498 tmsg->type = 3;
500 /* Set Negotiate Flags */
501 tmsg->flags = NEGOTIATE_FLAGS;
503 /* Domain */
504 tmsg->dom_off = sizeof(struct authenticate_message);
505 tmp = ((char*) tmsg) + tmsg->dom_off;
506 remlen = ((char *)tmsg)+msglen-tmp;
507 tmsg->dom_len1 = tmsg->dom_len2 = unicode_strconvcopy(tmp, domain, remlen);
508 tmp += tmsg->dom_len1;
509 remlen = ((char *)tmsg)+msglen-tmp;
511 /* User */
512 tmsg->user_off = tmsg->dom_off + tmsg->dom_len1;
513 tmsg->user_len1 = tmsg->user_len2 = unicode_strconvcopy(tmp, user, remlen);
514 tmp += tmsg->user_len1;
515 remlen = ((char *)tmsg)+msglen-tmp;
517 /* Host */
518 tmsg->host_off = tmsg->user_off + tmsg->user_len1;
519 tmsg->host_len1 = tmsg->host_len2 = unicode_strconvcopy(tmp, hostname, remlen);
520 tmp += tmsg->host_len1;
522 /* LM */
523 tmsg->lm_resp_len1 = tmsg->lm_resp_len2 = NTLMSSP_NT_OR_LM_KEY_LEN;
524 tmsg->lm_resp_off = tmsg->host_off + tmsg->host_len1;
526 LMOWFv1 (password, user, domain, response_key_lm);
527 DESL (response_key_lm, nonce, lm_challenge_response);
528 memcpy(tmp, lm_challenge_response, NTLMSSP_NT_OR_LM_KEY_LEN);
529 tmp += NTLMSSP_NT_OR_LM_KEY_LEN;
531 /* NT */
532 tmsg->nt_resp_len1 = tmsg->nt_resp_len2 = NTLMSSP_NT_OR_LM_KEY_LEN;
533 tmsg->nt_resp_off = tmsg->lm_resp_off + tmsg->lm_resp_len1;
535 NTOWFv1 (password, user, domain, response_key_nt);
536 DESL (response_key_nt, nonce, nt_challenge_response);
537 memcpy(tmp, nt_challenge_response, NTLMSSP_NT_OR_LM_KEY_LEN);
538 tmp += NTLMSSP_NT_OR_LM_KEY_LEN;
540 /* Session Key */
541 tmsg->sess_len1 = tmsg->sess_len2 = NTLMSSP_SESSION_KEY_LEN;
542 tmsg->sess_off = tmsg->nt_resp_off + tmsg->nt_resp_len1;
544 MD4(response_key_nt, 16, session_base_key);
546 KXKEY(session_base_key, lm_challenge_response, key_exchange_key);
548 NONCE (exported_session_key, 16);
550 *ntlm_key = (guchar *) g_strndup ((gchar *) exported_session_key, 16);
552 RC4K (key_exchange_key, exported_session_key, encrypted_random_session_key);
553 memcpy(tmp, encrypted_random_session_key, 16);
554 tmp += NTLMSSP_SESSION_KEY_LEN;
556 tmp = purple_base64_encode(exported_session_key, 16);
557 purple_debug_info("sipe", "Generated NTLM AUTHENTICATE message (%s)\n", tmp);
558 g_free(tmp);
560 tmp = purple_base64_encode((guchar*) tmsg, msglen);
561 g_free(tmsg);
562 return tmp;
565 /***********************************************
567 * End of merged code from original sip-ntlm.c
569 ***********************************************/
571 /* sip-sec-mech.h API implementation for NTLM */
572 static char *sipe_get_host_name();
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 ctx->domain = strdup(domain);
594 ctx->username = strdup(username);
595 ctx->password = strdup(password);
597 return SIP_SEC_E_OK;
600 static sip_uint32
601 sip_sec_init_sec_context__ntlm(SipSecContext context,
602 SipSecBuffer in_buff,
603 SipSecBuffer *out_buff,
604 const char *service_name)
606 context_ntlm ctx = (context_ntlm) context;
608 purple_debug_info("sipe", "sip_sec_init_sec_context__ntlm: in use\n");
610 ctx->step++;
611 if (ctx->step == 1) {
612 out_buff->length = 0;
613 out_buff->value = NULL;
614 // same behaviour as sspi
615 return SIP_SEC_I_CONTINUE_NEEDED;
617 } else {
618 guchar *ntlm_key;
619 guchar *nonce;
620 guint32 flags;
621 gchar *input_toked_base64;
622 gchar *gssapi_data;
624 input_toked_base64 = purple_base64_encode(in_buff.value,
625 in_buff.length);
627 nonce = g_memdup(purple_ntlm_parse_challenge(input_toked_base64, &flags), 8);
628 g_free(input_toked_base64);
630 gssapi_data = purple_ntlm_gen_authenticate(&ntlm_key,
631 ctx->username,
632 ctx->password,
633 sipe_get_host_name(),
634 ctx->domain,
635 nonce,
636 &flags);
637 g_free(nonce);
639 out_buff->value = purple_base64_decode(gssapi_data, &(out_buff->length));
640 g_free(gssapi_data);
642 g_free(ctx->key);
643 ctx->key = ntlm_key;
644 return SIP_SEC_E_OK;
649 * @param message a NULL terminated string to sign
652 static sip_uint32
653 sip_sec_make_signature__ntlm(SipSecContext context,
654 const char *message,
655 SipSecBuffer *signature)
657 gchar *signature_hex = purple_ntlm_sipe_signature_make(message,
658 ((context_ntlm) context)->key);
660 hex_str_to_bytes(signature_hex, signature);
661 g_free(signature_hex);
663 return SIP_SEC_E_OK;
667 * @param message a NULL terminated string to check signature of
668 * @return SIP_SEC_E_OK on success
670 static sip_uint32
671 sip_sec_verify_signature__ntlm(SipSecContext context,
672 const char *message,
673 SipSecBuffer signature)
675 char *signature_hex = bytes_to_hex_str(&signature);
676 gchar *signature_calc = purple_ntlm_sipe_signature_make(message,
677 ((context_ntlm) context)->key);
678 sip_uint32 res;
680 if (purple_ntlm_verify_signature(signature_calc, signature_hex)) {
681 res = SIP_SEC_E_OK;
682 } else {
683 res = SIP_SEC_E_INTERNAL_ERROR;
685 g_free(signature_calc);
686 g_free(signature_hex);
687 return(res);
690 static void
691 sip_sec_destroy_sec_context__ntlm(SipSecContext context)
693 context_ntlm ctx = (context_ntlm) context;
695 g_free(ctx->domain);
696 g_free(ctx->username);
697 g_free(ctx->password);
698 g_free(ctx->key);
699 g_free(ctx);
702 SipSecContext
703 sip_sec_create_context__ntlm(SipSecAuthType type)
705 context_ntlm context = g_malloc0(sizeof(struct _context_ntlm));
706 if (!context) return(NULL);
708 context->common.acquire_cred_func = sip_sec_acquire_cred__ntlm;
709 context->common.init_context_func = sip_sec_init_sec_context__ntlm;
710 context->common.destroy_context_func = sip_sec_destroy_sec_context__ntlm;
711 context->common.make_signature_func = sip_sec_make_signature__ntlm;
712 context->common.verify_signature_func = sip_sec_verify_signature__ntlm;
714 return((SipSecContext) context);
717 //@TODO refactor it somewhere to utils. Do we need compat with glib < 2.8 ?
718 char *sipe_get_host_name()
720 #if GLIB_CHECK_VERSION(2,8,0)
721 const gchar * hostname = g_get_host_name();
722 #else
723 static char hostname[256];
724 int ret = gethostname(hostname, sizeof(hostname));
725 hostname[sizeof(hostname) - 1] = '\0';
726 if (ret == -1 || hostname[0] == '\0') {
727 purple_debug(PURPLE_DEBUG_MISC, "sipe", "Error when getting host name. Using \"localhost.\"\n");
728 g_strerror(errno);
729 strcpy(hostname, "localhost");
731 #endif
732 /*const gchar * hostname = purple_get_host_name();*/
733 return (char *)hostname;
737 Local Variables:
738 mode: c
739 c-file-style: "bsd"
740 indent-tabs-mode: t
741 tab-width: 8
742 End: