6 * Copyright (C) 2009 pier11 <pier11@kinozal.tv>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 /* #include "util.h" */
31 #include "sip-sec-mech.h"
34 #include "sip-sec-ntlm.h"
35 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
38 #include "sip-sec-krb5.h"
39 #define sip_sec_create_context__Kerberos sip_sec_create_context__krb5
41 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
46 #include "sip-sec-sspi.h"
47 #define sip_sec_create_context__NTLM sip_sec_create_context__sspi
48 #define sip_sec_create_context__Kerberos sip_sec_create_context__sspi
49 #else /* USE_KERBEROS */
50 #include "sip-sec-ntlm.h"
51 #define sip_sec_create_context__NTLM sip_sec_create_context__ntlm
52 #define sip_sec_create_context__Kerberos sip_sec_create_context__NONE
53 #endif /* USE_KERBEROS */
57 gchar
*purple_base64_encode(const guchar
*data
, gsize len
);
58 guchar
*purple_base64_decode(const char *str
, gsize
*ret_len
);
60 /* Dummy initialization hook */
62 sip_sec_create_context__NONE(SIPE_UNUSED_PARAMETER SipSecAuthType type
)
67 /* sip_sec API method */
69 sip_sec_init_context(SipSecContext
*context
,
77 const char *input_toked_base64
)
79 SipSecBuffer in_buff
= {0, NULL
};
80 SipSecBuffer out_buff
= {0, NULL
};
81 gchar
*out_buff_base64
= NULL
;
84 /* Map authentication type to module initialization hook & name */
85 static const sip_sec_create_context_func
const auth_to_hook
[] = {
86 sip_sec_create_context__NONE
, /* AUTH_TYPE_UNSET */
87 sip_sec_create_context__NONE
, /* AUTH_TYPE_DIGEST */
88 sip_sec_create_context__NTLM
, /* AUTH_TYPE_NTLM */
89 sip_sec_create_context__Kerberos
, /* AUTH_TYPE_KERBEROS */
92 /* @TODO: Can *context != NULL actually happen? */
93 sip_sec_destroy_context(*context
);
95 *context
= (*(auth_to_hook
[type
]))(type
);
96 if (!*context
) return(NULL
);
98 (*context
)->sso
= sso
;
100 ret
= (*(*context
)->acquire_cred_func
)(*context
, domain
, username
, password
);
101 if (ret
!= SIP_SEC_E_OK
) {
102 purple_debug_info("sipe", "ERROR: sip_sec_init_context failed to acquire credentials.\n");
106 /* Type1 (empty) to send */
107 ret
= (*(*context
)->init_context_func
)(*context
, in_buff
, &out_buff
, target
);
108 if (ret
== SIP_SEC_E_OK
) {
109 out_buff_base64
= purple_base64_encode(out_buff
.value
, out_buff
.length
);
111 free_bytes_buffer(&out_buff
);
113 if (ret
== SIP_SEC_I_CONTINUE_NEEDED
) {
115 in_buff
.value
= purple_base64_decode(input_toked_base64
, &(in_buff
.length
));
116 ret
= (*(*context
)->init_context_func
)(*context
, in_buff
, &out_buff
, target
);
117 free_bytes_buffer(&in_buff
);
120 g_free(out_buff_base64
);
121 out_buff_base64
= purple_base64_encode(out_buff
.value
, out_buff
.length
);
122 free_bytes_buffer(&out_buff
);
125 *expires
= (*context
)->expires
;
127 return out_buff_base64
;
131 sip_sec_destroy_context(SipSecContext context
)
133 if (context
) (*context
->destroy_context_func
)(context
);
136 char * sip_sec_make_signature(SipSecContext context
, const char *message
)
138 SipSecBuffer signature
;
141 if(((*context
->make_signature_func
)(context
, message
, &signature
)) != SIP_SEC_E_OK
) {
142 purple_debug_info("sipe", "ERROR: sip_sec_make_signature failed. Unable to sign message!\n");
145 signature_hex
= bytes_to_hex_str(&signature
);
146 free_bytes_buffer(&signature
);
147 return signature_hex
;
150 int sip_sec_verify_signature(SipSecContext context
, const char *message
, const char *signature_hex
)
152 SipSecBuffer signature
;
155 hex_str_to_bytes(signature_hex
, &signature
);
156 res
= (*context
->verify_signature_func
)(context
, message
, signature
);
157 free_bytes_buffer(&signature
);
162 /* Utility Methods */
164 void hex_str_to_bytes(const char *hex_str
, SipSecBuffer
*bytes
)
170 bytes
->length
= strlen(hex_str
)/2;
171 bytes
->value
= g_malloc(bytes
->length
);
173 buff
= (guint8
*)bytes
->value
;
174 for (i
= 0; i
< bytes
->length
; i
++) {
175 two_digits
[0] = hex_str
[i
* 2];
176 two_digits
[1] = hex_str
[i
* 2 + 1];
177 two_digits
[2] = '\0';
178 buff
[i
] = (guint8
)strtoul(two_digits
, NULL
, 16);
182 void free_bytes_buffer(SipSecBuffer
*bytes
)
184 g_free(bytes
->value
);
189 char *bytes_to_hex_str(SipSecBuffer
*bytes
)
191 guint8
*buff
= (guint8
*)bytes
->value
;
192 char *res
= g_malloc(bytes
->length
* 2 + 1);
194 for (i
= 0, j
= 0; i
< bytes
->length
; i
++, j
+=2) {
195 sprintf(&res
[j
], "%02X", buff
[i
]);