~ubuntu-branches/debian/sid/kamailio/sid

« back to all changes in this revision

Viewing changes to .pc/upstream/0002-ims_auth-Fix-for-SIP-Digest-Segmentation-fault.patch/modules/ims_auth/authorize.c

  • Committer: Package Import Robot
  • Author(s): Victor Seva
  • Date: 2014-01-06 11:47:13 UTC
  • mfrom: (1.1.5)
  • Revision ID: package-import@ubuntu.com-20140106114713-t8xidp4arzrnyeya
Tags: 4.1.1-1
* New upstream release
* debian/patches:
  - add upstream fixes
* Added tls outbound websocket autheph dnssec modules
  - openssl exception added to their license
* removing sparc and ia64 from supported archs
  for mono module (Closes: #728915)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * $Id$
 
3
 *
 
4
 * Copyright (C) 2012 Smile Communications, jason.penton@smilecoms.com
 
5
 * Copyright (C) 2012 Smile Communications, richard.good@smilecoms.com
 
6
 * 
 
7
 * The initial version of this code was written by Dragos Vingarzan
 
8
 * (dragos(dot)vingarzan(at)fokus(dot)fraunhofer(dot)de and the
 
9
 * Fruanhofer Institute. It was and still is maintained in a separate
 
10
 * branch of the original SER. We are therefore migrating it to
 
11
 * Kamailio/SR and look forward to maintaining it from here on out.
 
12
 * 2011/2012 Smile Communications, Pty. Ltd.
 
13
 * ported/maintained/improved by 
 
14
 * Jason Penton (jason(dot)penton(at)smilecoms.com and
 
15
 * Richard Good (richard(dot)good(at)smilecoms.com) as part of an 
 
16
 * effort to add full IMS support to Kamailio/SR using a new and
 
17
 * improved architecture
 
18
 * 
 
19
 * NB: Alot of this code was originally part of OpenIMSCore,
 
20
 * FhG Fokus. 
 
21
 * Copyright (C) 2004-2006 FhG Fokus
 
22
 * Thanks for great work! This is an effort to 
 
23
 * break apart the various CSCF functions into logically separate
 
24
 * components. We hope this will drive wider use. We also feel
 
25
 * that in this way the architecture is more complete and thereby easier
 
26
 * to manage in the Kamailio/SR environment
 
27
 *
 
28
 * This file is part of Kamailio, a free SIP server.
 
29
 *
 
30
 * Kamailio is free software; you can redistribute it and/or modify
 
31
 * it under the terms of the GNU General Public License as published by
 
32
 * the Free Software Foundation; either version 2 of the License, or
 
33
 * (at your option) any later version
 
34
 *
 
35
 * Kamailio is distributed in the hope that it will be useful,
 
36
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
37
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
38
 * GNU General Public License for more details.
 
39
 *
 
40
 * You should have received a copy of the GNU General Public License 
 
41
 * along with this program; if not, write to the Free Software 
 
42
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
43
 * 
 
44
 */
 
45
 
 
46
#include <string.h>
 
47
#include "../../ut.h"
 
48
#include "../../str.h"
 
49
#include "../../basex.h"
 
50
#include "../../hashes.h"
 
51
#include "../../lib/srdb1/db.h"
 
52
#include "../../lib/srdb1/db_ut.h"
 
53
#include "../../dprint.h"
 
54
#include "../../parser/digest/digest.h"
 
55
#include "../../parser/hf.h"
 
56
#include "../../parser/parser_f.h"
 
57
#include "../../usr_avp.h"
 
58
#include "../../mod_fix.h"
 
59
#include "../../mem/mem.h"
 
60
#include "../cdp/diameter.h"
 
61
#include "../cdp/diameter_ims_code_result.h"
 
62
 
 
63
#include "cxdx_mar.h"
 
64
#include "cxdx_avp.h"
 
65
 
 
66
 
 
67
#include "../../lib/ims/ims_getters.h"
 
68
#include "../tm/tm_load.h"
 
69
#include "api.h"
 
70
#include "authims_mod.h"
 
71
#include "authorize.h"
 
72
#include "utils.h"
 
73
#include "../../action.h" /* run_actions */
 
74
 
 
75
extern unsigned char registration_default_algorithm_type; /**< fixed default algorithm for registration (if none present)       */
 
76
extern struct tm_binds tmb;
 
77
extern struct cdp_binds cdpb;
 
78
 
 
79
extern str registration_qop_str; /**< the qop options to put in the authorization challenges */
 
80
extern int av_request_at_sync; /**< how many auth vectors to request in a sync MAR              */
 
81
extern int av_request_at_once; /**< how many auth vectors to request in a MAR                           */
 
82
extern int auth_vector_timeout;
 
83
extern int auth_data_timeout; /**< timeout for a hash entry to expire when empty in sec         */
 
84
extern int auth_used_vector_timeout;
 
85
extern int add_authinfo_hdr;
 
86
extern int max_nonce_reuse;
 
87
extern str scscf_name_str;
 
88
extern int ignore_failed_auth;
 
89
extern int av_check_only_impu;
 
90
 
 
91
auth_hash_slot_t *auth_data; /**< Authentication vector hash table */
 
92
extern int auth_data_hash_size; /**< authentication vector hash table size */
 
93
 
 
94
 
 
95
static str empty_s = {0, 0};
 
96
 
 
97
str S_WWW = {"WWW", 3};
 
98
str S_Proxy = {"Proxy", 5};
 
99
str S_Authorization_AKA = {"%.*s-Authenticate: Digest realm=\"%.*s\","
 
100
    " nonce=\"%.*s\", algorithm=%.*s, ck=\"%.*s\", ik=\"%.*s\"%.*s\r\n", 107};
 
101
str S_Authorization_MD5 = {"%.*s-Authenticate: Digest realm=\"%.*s\","
 
102
    " nonce=\"%.*s\", algorithm=%.*s%.*s\r\n", 102};
 
103
 
 
104
str algorithm_types[] = {
 
105
    {"unknown", 7},
 
106
    {"AKAv1-MD5", 9},
 
107
    {"AKAv2-MD5", 9},
 
108
    {"Early-IMS", 9},
 
109
    {"MD5", 3},
 
110
    {"CableLabs-Digest", 16},
 
111
    {"3GPP-Digest", 11},
 
112
    {"TISPAN-HTTP_DIGEST_MD5", 22},
 
113
    {"NASS-Bundled", 12},
 
114
    {0, 0}
 
115
};
 
116
 
 
117
str auth_scheme_types[] = {
 
118
    {"unknown", 7},
 
119
    {"Digest-AKAv1-MD5", 16},
 
120
    {"Digest-AKAv2-MD5", 16},
 
121
    {"Early-IMS-Security", 18},
 
122
    {"Digest-MD5", 10},
 
123
    {"Digest", 6},
 
124
    {"SIP Digest", 10},
 
125
    {"HTTP_DIGEST_MD5", 15},
 
126
    {"NASS-Bundled", 12},
 
127
    {0, 0}
 
128
};
 
129
 
 
130
/**
 
131
 * Convert the SIP Algorithm to its type
 
132
 * @param algorithm - the SIP Algorithm
 
133
 * @returns the algorithm type
 
134
 */
 
135
unsigned char get_algorithm_type(str algorithm) {
 
136
    int i;
 
137
    for (i = 0; algorithm_types[i].len > 0; i++)
 
138
        if (algorithm_types[i].len == algorithm.len
 
139
                && strncasecmp(algorithm_types[i].s, algorithm.s, algorithm.len)
 
140
                == 0)
 
141
            return i;
 
142
    return AUTH_UNKNOWN;
 
143
}
 
144
 
 
145
/**
 
146
 * Convert the Diameter Authorization Scheme to its type
 
147
 * @param scheme - the Diameter Authorization Scheme
 
148
 * @returns the SIP Algorithm
 
149
 */
 
150
unsigned char get_auth_scheme_type(str scheme) {
 
151
    int i;
 
152
    for (i = 0; auth_scheme_types[i].len > 0; i++)
 
153
        if (auth_scheme_types[i].len == scheme.len &&
 
154
                strncasecmp(auth_scheme_types[i].s, scheme.s, scheme.len) == 0)
 
155
            return i;
 
156
    return AUTH_UNKNOWN;
 
157
}
 
158
 
 
159
static inline int get_ha1(struct username* _username, str* _domain,
 
160
        const str* _table, char* _ha1, db1_res_t** res) {
 
161
 
 
162
    return 0;
 
163
}
 
164
 
 
165
/*
 
166
 * Authorize digest credentials
 
167
 */
 
168
static int digest_authenticate(struct sip_msg* msg, str *realm,
 
169
        str *table, hdr_types_t hftype) {
 
170
    return 0;
 
171
}
 
172
 
 
173
/**
 
174
 * Starts the reg_await_timer for an authentication vector.
 
175
 * @param av - the authentication vector
 
176
 */
 
177
inline void start_reg_await_timer(auth_vector *av) {
 
178
    av->expires = get_ticks() + auth_vector_timeout;
 
179
    av->status = AUTH_VECTOR_SENT;
 
180
}
 
181
 
 
182
/**
 
183
 * Timer callback for reg await timers.
 
184
 * Drops the auth vectors that have been sent and are expired
 
185
 * Also drops the useless auth vectors - used and no longer needed
 
186
 * @param ticks - what's the time
 
187
 * @param param - a given parameter to be called with
 
188
 */
 
189
void reg_await_timer(unsigned int ticks, void* param) {
 
190
    auth_userdata *aud, *aud_next;
 
191
    auth_vector *av, *av_next;
 
192
    int i;
 
193
 
 
194
    LM_DBG("Looking for expired/useless at %d\n", ticks);
 
195
    for (i = 0; i < auth_data_hash_size; i++) {
 
196
        auth_data_lock(i);
 
197
        aud = auth_data[i].head;
 
198
        while (aud) {
 
199
            LM_DBG("Slot %4d <%.*s>\n",
 
200
                    aud->hash, aud->private_identity.len, aud->private_identity.s);
 
201
            aud_next = aud->next;
 
202
            av = aud->head;
 
203
            while (av) {
 
204
                LM_DBG(".. AV %4d - %d Exp %3d  %p\n",
 
205
                        av->item_number, av->status, (int) av->expires, av);
 
206
                av_next = av->next;
 
207
                if (av->status == AUTH_VECTOR_USELESS ||
 
208
                        ((av->status == AUTH_VECTOR_USED || av->status == AUTH_VECTOR_SENT) && av->expires < ticks)
 
209
                        ) {
 
210
                    LM_DBG("... dropping av %d - %d\n",
 
211
                            av->item_number, av->status);
 
212
                    if (av->prev) av->prev->next = av->next;
 
213
                    else aud->head = av->next;
 
214
                    if (av->next) av->next->prev = av->prev;
 
215
                    else aud->tail = av->prev;
 
216
                    free_auth_vector(av);
 
217
                }
 
218
                av = av_next;
 
219
            }
 
220
            if (!aud->head) {
 
221
                if (aud->expires == 0) {
 
222
                    LM_DBG("... started empty aud drop timer\n");
 
223
                    aud->expires = ticks + auth_data_timeout;
 
224
                } else
 
225
                    if (aud->expires < ticks) {
 
226
                    LM_DBG("... dropping aud \n");
 
227
                    if (aud->prev) aud->prev->next = aud->next;
 
228
                    else auth_data[i].head = aud->next;
 
229
                    if (aud->next) aud->next->prev = aud->prev;
 
230
                    else auth_data[i].tail = aud->prev;
 
231
                    free_auth_userdata(aud);
 
232
                }
 
233
            } else aud->expires = 0;
 
234
 
 
235
            aud = aud_next;
 
236
        }
 
237
        auth_data_unlock(i);
 
238
    }
 
239
    LM_DBG("[DONE] Looking for expired/useless at %d\n", ticks);
 
240
}
 
241
 
 
242
/*
 
243
 * Authenticate using Proxy-Authorize header field
 
244
 */
 
245
 
 
246
/*
 
247
int proxy_authenticate(struct sip_msg* _m, char* _realm, char* _table) {
 
248
    str srealm;
 
249
    str stable;
 
250
 
 
251
    if (_table == NULL) {
 
252
        LM_ERR("invalid table parameter\n");
 
253
        return -1;
 
254
    }
 
255
 
 
256
    stable.s = _table;
 
257
    stable.len = strlen(stable.s);
 
258
 
 
259
    if (get_str_fparam(&srealm, _m, (fparam_t*) _realm) < 0) {
 
260
        LM_ERR("failed to get realm value\n");
 
261
        return -1; //AUTH_ERROR;
 
262
    }
 
263
 
 
264
    if (srealm.len == 0) {
 
265
        LM_ERR("invalid realm parameter - empty value\n");
 
266
        return -1; //AUTH_ERROR;
 
267
    }
 
268
    LM_DBG("realm value [%.*s]\n", srealm.len, srealm.s);
 
269
 
 
270
    return digest_authenticate(_m, &srealm, &stable, HDR_PROXYAUTH_T);
 
271
}
 
272
 */
 
273
int challenge(struct sip_msg* msg, char* str1, char* str2, int is_proxy_auth, char *route) {
 
274
 
 
275
    str realm = {0, 0};
 
276
    unsigned int aud_hash;
 
277
    str private_identity, public_identity, auts = {0, 0}, nonce = {0, 0};
 
278
    auth_vector *av = 0;
 
279
    int algo_type;
 
280
    
 
281
    str route_name;
 
282
 
 
283
    saved_transaction_t* saved_t;
 
284
    tm_cell_t *t = 0;
 
285
    cfg_action_t* cfg_action;
 
286
 
 
287
    if (fixup_get_svalue(msg, (gparam_t*) route, &route_name) != 0) {
 
288
        LM_ERR("no async route block for assign_server_unreg\n");
 
289
        return -1;
 
290
    }
 
291
    
 
292
    LM_DBG("Looking for route block [%.*s]\n", route_name.len, route_name.s);
 
293
    int ri = route_get(&main_rt, route_name.s);
 
294
    if (ri < 0) {
 
295
        LM_ERR("unable to find route block [%.*s]\n", route_name.len, route_name.s);
 
296
        return -1;
 
297
    }
 
298
    cfg_action = main_rt.rlist[ri];
 
299
    if (cfg_action == NULL) {
 
300
        LM_ERR("empty action lists in route block [%.*s]\n", route_name.len, route_name.s);
 
301
        return -1;
 
302
    }
 
303
 
 
304
    if (get_str_fparam(&realm, msg, (fparam_t*) str1) < 0) {
 
305
        LM_ERR("failed to get realm value\n");
 
306
        return CSCF_RETURN_ERROR;
 
307
    }
 
308
 
 
309
    if (realm.len == 0) {
 
310
        LM_ERR("invalid realm value - empty content\n");
 
311
        return CSCF_RETURN_ERROR;
 
312
    }
 
313
 
 
314
    create_return_code(CSCF_RETURN_ERROR);
 
315
 
 
316
    LM_DBG("Need to challenge for realm [%.*s]\n", realm.len, realm.s);
 
317
 
 
318
    if (msg->first_line.type != SIP_REQUEST) {
 
319
        LM_ERR("This message is not a request\n");
 
320
        return CSCF_RETURN_ERROR;
 
321
    }
 
322
    if (!is_proxy_auth) {
 
323
        LM_DBG("Checking if REGISTER is authorized for realm [%.*s]...\n", realm.len, realm.s);
 
324
 
 
325
        /* First check the parameters */
 
326
        if (msg->first_line.u.request.method.len != 8 ||
 
327
                memcmp(msg->first_line.u.request.method.s, "REGISTER", 8) != 0) {
 
328
            LM_ERR("This message is not a REGISTER request\n");
 
329
            return CSCF_RETURN_ERROR;
 
330
        }
 
331
    }
 
332
 
 
333
    /* get the private_identity */
 
334
    private_identity = get_private_identity(msg, realm, is_proxy_auth);
 
335
    if (!private_identity.len) {
 
336
        LM_ERR("No private identity specified (Authorization: username)\n");
 
337
        stateful_request_reply(msg, 403, MSG_403_NO_PRIVATE);
 
338
        return CSCF_RETURN_BREAK;
 
339
    }
 
340
    /* get the public_identity */
 
341
    public_identity = get_public_identity(msg);
 
342
    if (!public_identity.len) {
 
343
        LM_ERR("No public identity specified (To:)\n");
 
344
        stateful_request_reply(msg, 403, MSG_403_NO_PUBLIC);
 
345
        return CSCF_RETURN_BREAK;
 
346
    }
 
347
 
 
348
    algo_type = registration_default_algorithm_type;
 
349
 
 
350
    /* check if it is a synchronization request */
 
351
    //TODO this is MAR syncing - have removed it currently - TOD maybe put back in
 
352
//    auts = ims_get_auts(msg, realm, is_proxy_auth);
 
353
//    if (auts.len) {
 
354
//        LM_DBG("IMS Auth Synchronization requested <%.*s>\n", auts.len, auts.s);
 
355
//
 
356
//        nonce = ims_get_nonce(msg, realm);
 
357
//        if (nonce.len == 0) {
 
358
//            LM_DBG("Nonce not found (Authorization: nonce)\n");
 
359
//            stateful_request_reply(msg, 403, MSG_403_NO_NONCE);
 
360
//            return CSCF_RETURN_BREAK;
 
361
//        }
 
362
//        av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_USED, &nonce, &aud_hash);
 
363
//        if (!av)
 
364
//            av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_SENT, &nonce, &aud_hash);
 
365
//
 
366
//        if (!av) {
 
367
//            LM_ERR("Nonce not regonized as sent, no sync!\n");
 
368
//            auts.len = 0;
 
369
//            auts.s = 0;
 
370
//        } else {
 
371
//            av->status = AUTH_VECTOR_USELESS;
 
372
//            auth_data_unlock(aud_hash);
 
373
//            av = 0;
 
374
//        }
 
375
//
 
376
//        //RICHARD REMOVED REALM - this is diameter realm set in cxdx not SIP domain
 
377
//        // if synchronization - force MAR - if MAR ok, old avs will be droped
 
378
//        multimedia_auth_request(msg, public_identity, private_identity, av_request_at_sync,
 
379
//                auth_scheme_types[algo_type], nonce, auts, scscf_name_str);
 
380
//    }
 
381
 
 
382
    //RICHARD changed this
 
383
    //Previous approach sent MAR, got MAA then put auth vectors into queue
 
384
    //Then we try and get that auth vector out the queue (it might be used by someone else so we loop)
 
385
    //new approach
 
386
    //we do MAR get MAA (asynchronously) get auth vector use it to pack the vector etc.
 
387
    //set it to sent and set an expires on it
 
388
    //then add it to the queue!
 
389
 
 
390
    /* loop because some other process might steal the auth_vector that we just retrieved */
 
391
    //while (!(av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_UNUSED, 0, &aud_hash))) {
 
392
 
 
393
    if ((av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_UNUSED, 0, &aud_hash))) {
 
394
        if (!av) {
 
395
            LM_ERR("Error retrieving an auth vector\n");
 
396
            return CSCF_RETURN_ERROR;
 
397
        }
 
398
 
 
399
        if (!pack_challenge(msg, realm, av, is_proxy_auth)) {
 
400
            stateful_request_reply(msg, 500, MSG_500_PACK_AV);
 
401
            auth_data_unlock(aud_hash);
 
402
            return CSCF_RETURN_ERROR;
 
403
        }
 
404
 
 
405
        start_reg_await_timer(av); //start the timer to remove stale or unused Auth Vectors
 
406
        if (is_proxy_auth) {
 
407
            stateful_request_reply(msg, 407, MSG_407_CHALLENGE);
 
408
        } else {
 
409
            stateful_request_reply(msg, 401, MSG_401_CHALLENGE);
 
410
        }
 
411
        auth_data_unlock(aud_hash);
 
412
 
 
413
    } else {
 
414
 
 
415
        //before we send lets suspend the transaction
 
416
        t = tmb.t_gett();
 
417
        if (t == NULL || t == T_UNDEFINED) {
 
418
            if (tmb.t_newtran(msg) < 0) {
 
419
                LM_ERR("cannot create the transaction for MAR async\n");
 
420
                stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
 
421
                return CSCF_RETURN_BREAK;
 
422
            }
 
423
            t = tmb.t_gett();
 
424
            if (t == NULL || t == T_UNDEFINED) {
 
425
                LM_ERR("cannot lookup the transaction\n");
 
426
                stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
 
427
                return CSCF_RETURN_BREAK;
 
428
            }
 
429
        }
 
430
 
 
431
        saved_t = shm_malloc(sizeof (saved_transaction_t));
 
432
        if (!saved_t) {
 
433
            LM_ERR("no more memory trying to save transaction state\n");
 
434
            return CSCF_RETURN_ERROR;
 
435
 
 
436
        }
 
437
        memset(saved_t, 0, sizeof (saved_transaction_t));
 
438
        saved_t->act = cfg_action;
 
439
 
 
440
        saved_t->realm.s = (char*) shm_malloc(realm.len + 1);
 
441
        if (!saved_t->realm.s) {
 
442
            LM_ERR("no more memory trying to save transaction state : callid\n");
 
443
            shm_free(saved_t);
 
444
            return CSCF_RETURN_ERROR;
 
445
        }
 
446
        memset(saved_t->realm.s, 0, realm.len + 1);
 
447
        memcpy(saved_t->realm.s, realm.s, realm.len);
 
448
        saved_t->realm.len = realm.len;
 
449
 
 
450
 
 
451
        saved_t->is_proxy_auth = is_proxy_auth;
 
452
 
 
453
        LM_DBG("Suspending SIP TM transaction\n");
 
454
        if (tmb.t_suspend(msg, &saved_t->tindex, &saved_t->tlabel) < 0) {
 
455
            LM_ERR("failed to suspend the TM processing\n");
 
456
            free_saved_transaction_data(saved_t);
 
457
 
 
458
            stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
 
459
            return CSCF_RETURN_BREAK;
 
460
        }
 
461
 
 
462
        if (multimedia_auth_request(msg, public_identity, private_identity, av_request_at_once,
 
463
                auth_scheme_types[algo_type], nonce, auts, scscf_name_str, saved_t)!=0) {
 
464
            LM_ERR("ERR:I_MAR: Error sending MAR or MAR time-out\n");
 
465
            tmb.t_cancel_suspend(saved_t->tindex, saved_t->tlabel);
 
466
            free_saved_transaction_data(saved_t);
 
467
            stateful_request_reply(msg, 480, MSG_480_DIAMETER_ERROR);
 
468
            return CSCF_RETURN_BREAK;
 
469
        }
 
470
    }
 
471
    return CSCF_RETURN_BREAK;
 
472
}
 
473
 
 
474
int www_challenge(struct sip_msg* msg, char* _route, char* str1, char* str2) {
 
475
    return challenge(msg, str1, str2, 0, _route);
 
476
}
 
477
 
 
478
int proxy_challenge(struct sip_msg* msg, char* _route, char* str1, char* str2) {
 
479
    return challenge(msg, str1, str2, 1, _route);
 
480
}
 
481
 
 
482
/**
 
483
 * Replies to a REGISTER and also adds the need headers
 
484
 * Path and Service-Route are added.
 
485
 * @param msg - the SIP message to operator on
 
486
 * @param code - Reason Code for the response
 
487
 * @param text - Reason Phrase for the response
 
488
 * @returns #CSCF_RETURN_TRUE on success or #CSCF_RETURN_FALSE if not added
 
489
 */
 
490
int stateful_request_reply(struct sip_msg *msg, int code, char *text) {
 
491
    unsigned int hash, label;
 
492
    struct hdr_field *h;
 
493
    str t = {0, 0};
 
494
    if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
 
495
        LM_ERR("Error parsing headers\n");
 
496
        return -1;
 
497
    }
 
498
    h = msg->headers;
 
499
    while (h) {
 
500
        if (h->name.len == 4 &&
 
501
                strncasecmp(h->name.s, "Path", 4) == 0) {
 
502
            t.s = h->name.s;
 
503
            t.len = h->len;
 
504
            ims_add_header_rpl(msg, &(t));
 
505
        }
 
506
        h = h->next;
 
507
    }
 
508
 
 
509
    /*if (code==200){
 
510
            ims_add_header_rpl(msg,&scscf_service_route);
 
511
    }*/ //TODO: need to get the service route from somewhere - registrar?
 
512
 
 
513
 
 
514
    if (tmb.t_get_trans_ident(msg, &hash, &label) < 0) {
 
515
        if (tmb.t_newtran(msg) < 0)
 
516
            LM_INFO("Failed creating SIP transaction\n");
 
517
    }
 
518
    return tmb.t_reply(msg, code, text);
 
519
 
 
520
}
 
521
 
 
522
/**
 
523
 * Replies to a REGISTER and also adds the need headers
 
524
 * Path and Service-Route are added.
 
525
 * @param msg - the SIP message to operator on
 
526
 * @param code - Reason Code for the response
 
527
 * @param text - Reason Phrase for the response
 
528
 * @returns #CSCF_RETURN_TRUE on success or #CSCF_RETURN_FALSE if not added
 
529
 */
 
530
 
 
531
int stateful_request_reply_async(struct cell* t_cell, struct sip_msg *msg, int code, char *text) {
 
532
    struct hdr_field *h;
 
533
    str t = {0, 0};
 
534
    if (parse_headers(msg, HDR_EOH_F, 0) < 0) {
 
535
        LM_ERR("Error parsing headers\n");
 
536
        return -1;
 
537
    }
 
538
    h = msg->headers;
 
539
    while (h) {
 
540
        if (h->name.len == 4 &&
 
541
                strncasecmp(h->name.s, "Path", 4) == 0) {
 
542
            t.s = h->name.s;
 
543
            t.len = h->len;
 
544
            ims_add_header_rpl(msg, &(t));
 
545
        }
 
546
        h = h->next;
 
547
    }
 
548
 
 
549
    return tmb.t_reply_trans(t_cell, msg, code, text);
 
550
 
 
551
}
 
552
 
 
553
int authenticate(struct sip_msg* msg, char* _realm, char* str2, int is_proxy_auth) {
 
554
    int ret = -1; //CSCF_RETURN_FALSE;
 
555
    unsigned int aud_hash = 0;
 
556
    str realm;
 
557
    str private_identity, public_identity;
 
558
    str nonce, response16, nc, cnonce, qop_str = {0, 0}, body, *next_nonce = &empty_s;
 
559
    enum qop_type qop = QOP_UNSPEC;
 
560
    str uri = {0, 0};
 
561
    HASHHEX expected, ha1, hbody, rspauth;
 
562
    int expected_len = 32;
 
563
    int expires = 0;
 
564
    auth_vector *av = 0;
 
565
    uint32_t nc_parsed = 0; /* the numerical representation of nc */
 
566
 
 
567
    ret = AUTH_ERROR;
 
568
 
 
569
    if (get_str_fparam(&realm, msg, (fparam_t*) _realm) < 0) {
 
570
        LM_ERR("failed to get realm value\n");
 
571
        return AUTH_NO_CREDENTIALS;
 
572
    }
 
573
 
 
574
    if (realm.len == 0) {
 
575
        LM_ERR("invalid realm value - empty content\n");
 
576
        return AUTH_NO_CREDENTIALS;
 
577
    }
 
578
 
 
579
    if (msg->first_line.type != SIP_REQUEST) {
 
580
        LM_ERR("This message is not a request\n");
 
581
        ret = AUTH_ERROR;
 
582
        goto end;
 
583
    }
 
584
    if (!is_proxy_auth) {
 
585
        LM_DBG("Checking if REGISTER is authorized for realm [%.*s]...\n", realm.len, realm.s);
 
586
 
 
587
        /* First check the parameters */
 
588
        if (msg->first_line.u.request.method.len != 8 ||
 
589
                memcmp(msg->first_line.u.request.method.s, "REGISTER", 8) != 0) {
 
590
            LM_ERR("This message is not a REGISTER request\n");
 
591
            ret = AUTH_ERROR;
 
592
            goto end;
 
593
        }
 
594
    }
 
595
 
 
596
    if (!realm.len) {
 
597
        LM_ERR("No realm found\n");
 
598
        return 0; //CSCF_RETURN_BREAK;
 
599
    }
 
600
 
 
601
    private_identity = get_private_identity(msg, realm, is_proxy_auth);
 
602
    if (!private_identity.len) {
 
603
        LM_ERR("private identity missing\n");
 
604
        return AUTH_NO_CREDENTIALS;
 
605
    }
 
606
 
 
607
    public_identity = get_public_identity(msg);
 
608
    if (!public_identity.len) {
 
609
        LM_ERR("public identity missing\n");
 
610
        return AUTH_NO_CREDENTIALS;
 
611
    }
 
612
 
 
613
    if (!get_nonce_response(msg, realm, &nonce, &response16, &qop, &qop_str, &nc, &cnonce, &uri, is_proxy_auth) ||
 
614
            !nonce.len || !response16.len) {
 
615
        LM_DBG("Nonce or response missing: nonce len [%i], response16 len[%i]\n", nonce.len, response16.len);
 
616
        return AUTH_ERROR;
 
617
    }
 
618
 
 
619
    if (qop == QOP_AUTHINT) {
 
620
        body = ims_get_body(msg);
 
621
        calc_H(&body, hbody);
 
622
    }
 
623
 
 
624
    /* first, look for an already used vector (if nonce reuse is enabled) */
 
625
    if (max_nonce_reuse > 0) {
 
626
        LM_DBG("look for an already used vector for %.*s\n",
 
627
                private_identity.len, private_identity.s);
 
628
        av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_USED, &nonce, &aud_hash);
 
629
    }
 
630
 
 
631
    if (!av) {
 
632
        /* if none found, or nonce reuse is disabled, look for a fresh vector
 
633
         * We should also drop every other used vector at this point
 
634
         * (there souldn't be more than one) */
 
635
 
 
636
        auth_userdata *aud;
 
637
        auth_vector *av_it;
 
638
        aud = get_auth_userdata(private_identity, public_identity);
 
639
        if (aud) {
 
640
            av_it = aud->head;
 
641
            while (av_it) {
 
642
                if (av_it->status == AUTH_VECTOR_USED) {
 
643
                    LM_DBG("vector %p is marked for deletion\n", av_it);
 
644
                    av_it->status = AUTH_VECTOR_USELESS;
 
645
                }
 
646
                av_it = av_it->next;
 
647
            }
 
648
            auth_data_unlock(aud->hash);
 
649
        }
 
650
 
 
651
        LM_DBG("look for a fresh vector for %.*s\n",
 
652
                private_identity.len, private_identity.s);
 
653
        av = get_auth_vector(private_identity, public_identity, AUTH_VECTOR_SENT, &nonce, &aud_hash);
 
654
    }
 
655
 
 
656
    LM_INFO("uri=%.*s nonce=%.*s response=%.*s qop=%.*s nc=%.*s cnonce=%.*s hbody=%.*s\n",
 
657
            uri.len, uri.s,
 
658
            nonce.len, nonce.s,
 
659
            response16.len, response16.s,
 
660
            qop_str.len, qop_str.s,
 
661
            nc.len, nc.s,
 
662
            cnonce.len, cnonce.s,
 
663
            32, hbody);
 
664
 
 
665
    if (!av) {
 
666
        LM_ERR("no matching auth vector found - maybe timer expired\n");
 
667
 
 
668
        if (ignore_failed_auth) {
 
669
            LM_WARN("NB: Ignoring all failed auth - check your config if you don't expect this\n");
 
670
            ret = AUTH_OK;
 
671
        }
 
672
 
 
673
        goto end;
 
674
    }
 
675
 
 
676
    if (qop != QOP_UNSPEC) {
 
677
        /* if QOP is sent, nc must be specified */
 
678
        /* the expected nc is the last used one plus 1 */
 
679
        int p;
 
680
        for (p = 0; p < 8; ++p) { /* nc is 8LHEX (RFC 2617 §3.2.2) */
 
681
            nc_parsed = (nc_parsed << 4) | UNHEX((int) nc.s[p]);
 
682
        }
 
683
        LM_DBG("nc is %08x, expected: %08x\n",
 
684
                nc_parsed, av->use_nb + 1);
 
685
        if (nc_parsed <= av->use_nb) { /* nc is lower than expected */
 
686
            ret = AUTH_NONCE_REUSED;
 
687
            av->status = AUTH_VECTOR_USELESS; /* invalidate this vector if any mistake/error occurs */
 
688
            goto cleanup;
 
689
        } else if (nc_parsed > av->use_nb + 1) { /* nc is bigger than expected */
 
690
            ret = AUTH_ERROR;
 
691
            av->status = AUTH_VECTOR_USELESS;
 
692
            goto cleanup;
 
693
        }
 
694
    }
 
695
 
 
696
    switch (av->type) {
 
697
        case AUTH_AKAV1_MD5:
 
698
        case AUTH_AKAV2_MD5:
 
699
        case AUTH_MD5:
 
700
            calc_HA1(HA_MD5, &private_identity, &realm, &(av->authorization), &(av->authenticate), &cnonce, ha1);
 
701
            calc_response(ha1, &(av->authenticate),
 
702
                    &nc,
 
703
                    &cnonce,
 
704
                    &qop_str,
 
705
                    qop == QOP_AUTHINT,
 
706
                    &msg->first_line.u.request.method, &uri, hbody, expected);
 
707
            LM_INFO("UE said: %.*s and we  expect %.*s ha1 %.*s (%.*s)\n",
 
708
                    response16.len, response16.s, /*av->authorization.len,av->authorization.s,*/32, expected, 32, ha1, msg->first_line.u.request.method.len, msg->first_line.u.request.method.s);
 
709
            break;
 
710
        default:
 
711
            LM_ERR("algorithm %.*s is not handled.\n",
 
712
                    algorithm_types[av->type].len, algorithm_types[av->type].s);
 
713
            ret = AUTH_ERROR;
 
714
            goto cleanup; /* release aud before returning */
 
715
    }
 
716
 
 
717
    expires = cscf_get_max_expires(msg, 0);
 
718
 
 
719
    if (response16.len == expected_len && strncasecmp(response16.s, expected, response16.len) == 0) {
 
720
        if (max_nonce_reuse > 0 && av->status == AUTH_VECTOR_SENT) {
 
721
            /* first use of a reusable vector */
 
722
            /* set the vector's new timeout */
 
723
            LM_DBG("vector %p now expires in %d seconds\n", av, auth_used_vector_timeout);
 
724
            av->expires = get_ticks() + auth_used_vector_timeout;
 
725
        }
 
726
        av->use_nb++;
 
727
        LM_DBG("vector %p successfully used %d time(s)\n", av, av->use_nb);
 
728
 
 
729
        if (av->use_nb == max_nonce_reuse + 1) {
 
730
            LM_DBG("vector %p isn't fresh anymore, recycle it with a new nonce\n", av);
 
731
 
 
732
            int i;
 
733
            char y[NONCE_LEN];
 
734
            for (i = 0; i < NONCE_LEN; i++)
 
735
                y[i] = (unsigned char) ((int) (256.0 * rand() / (RAND_MAX + 1.0)));
 
736
 
 
737
            if (unlikely((av->authenticate.len < 2 * NONCE_LEN))) {
 
738
                if (av->authenticate.s) {
 
739
                    shm_free(av->authenticate.s);
 
740
                }
 
741
                av->authenticate.len = 2 * NONCE_LEN;
 
742
                av->authenticate.s = shm_malloc(av->authenticate.len);
 
743
            }
 
744
 
 
745
            if (!av->authenticate.s) {
 
746
                LM_ERR("new_auth_vector: failed allocating %d bytes!\n", av->authenticate.len);
 
747
                av->authenticate.len = 0;
 
748
                goto cleanup;
 
749
            }
 
750
 
 
751
            av->authenticate.len = bin_to_base16(y, NONCE_LEN, av->authenticate.s);
 
752
 
 
753
            next_nonce = &(av->authenticate);
 
754
            av->status = AUTH_VECTOR_USED;
 
755
            av->use_nb = 0;
 
756
            av->expires = get_ticks() + auth_used_vector_timeout; /* reset the timer */
 
757
 
 
758
        } else if (expires == 0) { /* de-registration */
 
759
            LM_DBG("de-registration, vector %p isn't needed anymore\n", av);
 
760
            av->status = AUTH_VECTOR_USELESS;
 
761
        } else {
 
762
            av->status = AUTH_VECTOR_USED;
 
763
            /* nextnonce is the current nonce */
 
764
            next_nonce = &nonce;
 
765
        }
 
766
        ret = AUTH_OK;
 
767
 
 
768
        if (add_authinfo_hdr && expires != 0 /* don't add auth. info if de-registation */) {
 
769
            /* calculate rspauth */
 
770
            calc_response(ha1, &nonce,
 
771
                    &nc,
 
772
                    &cnonce,
 
773
                    &qop_str,
 
774
                    qop == QOP_AUTHINT,
 
775
                    0, &uri, hbody, rspauth);
 
776
 
 
777
            add_authinfo_resp_hdr(msg, *next_nonce, qop_str, rspauth, cnonce, nc);
 
778
        }
 
779
 
 
780
 
 
781
    } else {
 
782
        char authorise[200];
 
783
        char authenticate_bin[200];
 
784
        char authenticate_hex[200];
 
785
        memset(authorise, 0, 200);
 
786
        memset(authenticate_bin, 0, 200);
 
787
        memset(authenticate_hex, 0, 200);
 
788
 
 
789
        int authorise_len = bin_to_base16(av->authorization.s, av->authorization.len, authorise);
 
790
        int authenticate_len = base64_to_bin(av->authenticate.s, av->authenticate.len, authenticate_bin);
 
791
        int authenticate_hex_len = bin_to_base16(authenticate_bin, authenticate_len, authenticate_hex);
 
792
        av->status = AUTH_VECTOR_USELESS; /* first mistake, you're out! (but maybe it's synchronization) */
 
793
        LM_DBG("UE said: %.*s, but we expect %.*s : authenticate(b64) is [%.*s], authenticate(hex) is [%.*s], authorise is [%d] [%.*s]\n",
 
794
                response16.len, response16.s,
 
795
                32, expected,
 
796
                av->authenticate.len, av->authenticate.s,
 
797
                authenticate_hex_len,authenticate_hex,
 
798
                authorise_len,
 
799
                authorise_len, authorise);
 
800
        ret = AUTH_INVALID_PASSWORD;
 
801
    }
 
802
 
 
803
    if (ignore_failed_auth) {
 
804
        LM_WARN("NB: Ignoring all failed auth - check your config if you don't expect this\n");
 
805
        ret = AUTH_OK;
 
806
    }
 
807
 
 
808
cleanup:
 
809
    auth_data_unlock(aud_hash);
 
810
end:
 
811
    return ret;
 
812
}
 
813
 
 
814
/*
 
815
 * Authenticate using WWW-Authorize header field
 
816
 */
 
817
int www_authenticate(struct sip_msg* msg, char* _realm, char* str2) {
 
818
    return authenticate(msg, _realm, str2, 0);
 
819
}
 
820
 
 
821
/*
 
822
 * Authenticate using WWW-Authorize header field
 
823
 */
 
824
int proxy_authenticate(struct sip_msg* msg, char* _realm, char* str2) {
 
825
    return authenticate(msg, _realm, str2, 1);
 
826
}
 
827
 
 
828
/**
 
829
 * @brief bind functions to IMS AUTH API structure
 
830
 */
 
831
int bind_ims_auth(ims_auth_api_t * api) {
 
832
    if (!api) {
 
833
        ERR("Invalid parameter value\n");
 
834
        return -1;
 
835
    }
 
836
    api->digest_authenticate = digest_authenticate;
 
837
 
 
838
    return 0;
 
839
}
 
840
 
 
841
/**
 
842
 * Retrieve an authentication vector.
 
843
 * \note returns with a lock, so unlock it when done
 
844
 * @param private_identity - the private identity
 
845
 * @param public_identity - the public identity
 
846
 * @param status - the status of the authentication vector
 
847
 * @param nonce - the nonce in the auth vector
 
848
 * @param hash - the hash to unlock when done
 
849
 * @returns the auth_vector* if found or NULL if not
 
850
 */
 
851
auth_vector * get_auth_vector(str private_identity, str public_identity, int status, str *nonce, unsigned int *hash) {
 
852
    auth_userdata *aud;
 
853
    auth_vector *av;
 
854
    aud = get_auth_userdata(private_identity, public_identity);
 
855
    if (!aud) {
 
856
        LM_ERR("no auth userdata\n");
 
857
        goto error;
 
858
    }
 
859
 
 
860
    av = aud->head;
 
861
    while (av) {
 
862
        LM_DBG("looping through AV status is %d and were looking for %d\n", av->status, status);
 
863
        if (av->status == status && (nonce == 0 || (nonce->len == av->authenticate.len && memcmp(nonce->s, av->authenticate.s, nonce->len) == 0))) {
 
864
            LM_DBG("Found result\n");
 
865
            *hash = aud->hash;
 
866
            return av;
 
867
        }
 
868
        av = av->next;
 
869
    }
 
870
 
 
871
error:
 
872
    if (aud) auth_data_unlock(aud->hash);
 
873
    return 0;
 
874
}
 
875
 
 
876
/**
 
877
 * Locks the required slot of the auth_data.
 
878
 * @param hash - the index of the slot
 
879
 */
 
880
inline void auth_data_lock(unsigned int hash) {
 
881
    lock_get(auth_data[(hash)].lock);
 
882
}
 
883
 
 
884
/**
 
885
 * UnLocks the required slot of the auth_data
 
886
 * @param hash - the index of the slot
 
887
 */
 
888
inline void auth_data_unlock(unsigned int hash) {
 
889
    lock_release(auth_data[(hash)].lock);
 
890
}
 
891
 
 
892
/**
 
893
 * Initializes the Authorization Data structures.
 
894
 * @param size - size of the hash table
 
895
 * @returns 1 on success or 0 on error
 
896
 */
 
897
int auth_data_init(int size) {
 
898
    int i;
 
899
    auth_data = shm_malloc(sizeof (auth_hash_slot_t) * size);
 
900
    if (!auth_data) {
 
901
        LM_ERR("error allocating mem\n");
 
902
        return 0;
 
903
    }
 
904
    memset(auth_data, 0, sizeof (auth_hash_slot_t) * size);
 
905
    auth_data_hash_size = size;
 
906
    for (i = 0; i < size; i++) {
 
907
        auth_data[i].lock = lock_alloc();
 
908
        lock_init(auth_data[i].lock);
 
909
    }
 
910
    return 1;
 
911
}
 
912
 
 
913
/**
 
914
 * Destroy the Authorization Data structures */
 
915
void auth_data_destroy() {
 
916
    int i;
 
917
    auth_userdata *aud, *next;
 
918
    for (i = 0; i < auth_data_hash_size; i++) {
 
919
        auth_data_lock(i);
 
920
        lock_destroy(auth_data[i].lock);
 
921
        lock_dealloc(auth_data[i].lock);
 
922
        aud = auth_data[i].head;
 
923
        while (aud) {
 
924
            next = aud->next;
 
925
            free_auth_userdata(aud);
 
926
            aud = next;
 
927
        }
 
928
    }
 
929
    if (auth_data) shm_free(auth_data);
 
930
}
 
931
 
 
932
/**
 
933
 * Create new authorization vector
 
934
 * @param item_number - number to index it in the vectors list
 
935
 * @param auth_scheme - Diameter Authorization Scheme
 
936
 * @param authenticate - the challenge
 
937
 * @param authorization - the expected response
 
938
 * @param ck - the cypher key
 
939
 * @param ik - the integrity key
 
940
 * @returns the new auth_vector* or NULL on error
 
941
 */
 
942
auth_vector * new_auth_vector(int item_number, str auth_scheme, str authenticate,
 
943
        str authorization, str ck, str ik) {
 
944
    auth_vector *x = 0;
 
945
    x = shm_malloc(sizeof (auth_vector));
 
946
    if (!x) {
 
947
        LM_ERR("error allocating mem\n");
 
948
        goto done;
 
949
    }
 
950
    memset(x, 0, sizeof (auth_vector));
 
951
    x->item_number = item_number;
 
952
    x->type = get_auth_scheme_type(auth_scheme);
 
953
    switch (x->type) {
 
954
        case AUTH_AKAV1_MD5:
 
955
        case AUTH_AKAV2_MD5:
 
956
            /* AKA */
 
957
            x->authenticate.len = authenticate.len * 4 / 3 + 4;
 
958
            x->authenticate.s = shm_malloc(x->authenticate.len);
 
959
            if (!x->authenticate.s) {
 
960
                LM_ERR("error allocating mem\n");
 
961
                goto done;
 
962
            }
 
963
            x->authenticate.len = bin_to_base64(authenticate.s, authenticate.len,
 
964
                    x->authenticate.s);
 
965
 
 
966
            x->authorization.len = authorization.len;
 
967
            x->authorization.s = shm_malloc(x->authorization.len);
 
968
            if (!x->authorization.s) {
 
969
                LM_ERR("error allocating mem\n");
 
970
                goto done;
 
971
            }
 
972
            memcpy(x->authorization.s, authorization.s, authorization.len);
 
973
            x->ck.len = ck.len;
 
974
            x->ck.s = shm_malloc(ck.len);
 
975
            if (!x->ck.s) {
 
976
                LM_ERR("error allocating mem\n");
 
977
                goto done;
 
978
            }
 
979
            memcpy(x->ck.s, ck.s, ck.len);
 
980
 
 
981
            x->ik.len = ik.len;
 
982
            x->ik.s = shm_malloc(ik.len);
 
983
            if (!x->ik.s) {
 
984
                LM_ERR("error allocating mem\n");
 
985
                goto done;
 
986
            }
 
987
            memcpy(x->ik.s, ik.s, ik.len);
 
988
            break;
 
989
 
 
990
        case AUTH_MD5:
 
991
            /* MD5 */
 
992
            x->authenticate.len = authenticate.len * 2;
 
993
            x->authenticate.s = shm_malloc(x->authenticate.len);
 
994
            if (!x->authenticate.s) {
 
995
                LM_ERR("new_auth_vector: error allocating mem\n");
 
996
                goto done;
 
997
            }
 
998
            x->authenticate.len = bin_to_base16(authenticate.s, authenticate.len,
 
999
                    x->authenticate.s);
 
1000
 
 
1001
            x->authorization.len = authorization.len;
 
1002
            x->authorization.s = shm_malloc(x->authorization.len);
 
1003
            if (!x->authorization.s) {
 
1004
                LM_ERR("new_auth_vector: error allocating mem\n");
 
1005
                goto done;
 
1006
            }
 
1007
            memcpy(x->authorization.s, authorization.s, authorization.len);
 
1008
            x->authorization.len = authorization.len;
 
1009
            break;
 
1010
        case AUTH_DIGEST:
 
1011
        case AUTH_SIP_DIGEST:
 
1012
        {
 
1013
            int i;
 
1014
            char y[NONCE_LEN];
 
1015
            for (i = 0; i < NONCE_LEN; i++)
 
1016
                y[i] = (unsigned char) ((int) (256.0 * rand() / (RAND_MAX + 1.0)));
 
1017
            x->authenticate.len = 2 * NONCE_LEN;
 
1018
            x->authenticate.s = shm_malloc(x->authenticate.len);
 
1019
            if (!x->authenticate.s) {
 
1020
                LM_ERR("new_auth_vector: failed allocating %d bytes!\n", x->authenticate.len);
 
1021
                x->authenticate.len = 0;
 
1022
                goto done;
 
1023
            }
 
1024
            x->authenticate.len = bin_to_base16(y, NONCE_LEN, x->authenticate.s);
 
1025
        }
 
1026
 
 
1027
            x->authorization.len = authorization.len;
 
1028
            x->authorization.s = shm_malloc(x->authorization.len);
 
1029
            if (!x->authorization.s) {
 
1030
                LM_ERR("new_auth_vector: error allocating mem\n");
 
1031
                x->authorization.len = 0;
 
1032
                goto done;
 
1033
            }
 
1034
            memcpy(x->authorization.s, authorization.s, authorization.len);
 
1035
            x->authorization.len = authorization.len;
 
1036
 
 
1037
            break;
 
1038
        case AUTH_HTTP_DIGEST_MD5:
 
1039
            x->authenticate.len = authenticate.len;
 
1040
            x->authenticate.s = shm_malloc(x->authenticate.len);
 
1041
            if (!x->authenticate.s) {
 
1042
                LM_ERR("new_auth_vector: error allocating mem\n");
 
1043
                x->authenticate.len = 0;
 
1044
                goto done;
 
1045
            }
 
1046
            memcpy(x->authenticate.s, authenticate.s, authenticate.len);
 
1047
 
 
1048
            x->authorization.len = authorization.len;
 
1049
            x->authorization.s = shm_malloc(x->authorization.len);
 
1050
            if (!x->authorization.s) {
 
1051
                LM_ERR("new_auth_vector: error allocating mem\n");
 
1052
                x->authorization.len = 0;
 
1053
                goto done;
 
1054
            }
 
1055
            memcpy(x->authorization.s, authorization.s, authorization.len);
 
1056
            break;
 
1057
        case AUTH_EARLY_IMS:
 
1058
            /* early IMS */
 
1059
            x->authenticate.len = 0;
 
1060
            x->authenticate.s = 0;
 
1061
            x->authorization.len = authorization.len;
 
1062
            x->authorization.s = shm_malloc(x->authorization.len);
 
1063
            if (!x->authorization.s) {
 
1064
                LM_ERR("new_auth_vector: error allocating mem\n");
 
1065
                goto done;
 
1066
            }
 
1067
            memcpy(x->authorization.s, authorization.s, authorization.len);
 
1068
            x->authorization.len = authorization.len;
 
1069
            break;
 
1070
        case AUTH_NASS_BUNDLED:
 
1071
            /* NASS-Bundled */
 
1072
            x->authenticate.len = 0;
 
1073
            x->authenticate.s = 0;
 
1074
            x->authorization.len = authorization.len;
 
1075
            x->authorization.s = shm_malloc(x->authorization.len);
 
1076
            if (!x->authorization.s) {
 
1077
                LM_ERR("new_auth_vector: error allocating mem\n");
 
1078
                goto done;
 
1079
            }
 
1080
            memcpy(x->authorization.s, authorization.s, authorization.len);
 
1081
            x->authorization.len = authorization.len;
 
1082
            break;
 
1083
 
 
1084
        default:
 
1085
            /* all else */
 
1086
            x->authenticate.len = 0;
 
1087
            x->authenticate.s = 0;
 
1088
 
 
1089
    }
 
1090
 
 
1091
    x->use_nb = 0;
 
1092
 
 
1093
    x->next = 0;
 
1094
    x->prev = 0;
 
1095
    x->status = AUTH_VECTOR_UNUSED;
 
1096
    x->expires = 0;
 
1097
 
 
1098
done:
 
1099
    return x;
 
1100
}
 
1101
 
 
1102
/**
 
1103
 * Frees the memory taken by a authentication vector
 
1104
 * @param av - the vector to be freed
 
1105
 */
 
1106
void free_auth_vector(auth_vector * av) {
 
1107
    if (av) {
 
1108
        if (av->authenticate.s) shm_free(av->authenticate.s);
 
1109
        if (av->authorization.s) shm_free(av->authorization.s);
 
1110
        if (av->ck.s) shm_free(av->ck.s);
 
1111
        if (av->ik.s) shm_free(av->ik.s);
 
1112
        shm_free(av);
 
1113
    }
 
1114
}
 
1115
 
 
1116
/**
 
1117
 * Creates a new Authorization Userdata structure.
 
1118
 * @param private_identity - the private identity to attach to
 
1119
 * @param public_identity - the public identity to attach to
 
1120
 * @returns the new auth_userdata* on success or NULL on error
 
1121
 */
 
1122
auth_userdata * new_auth_userdata(str private_identity, str public_identity) {
 
1123
    auth_userdata *x = 0;
 
1124
 
 
1125
    x = shm_malloc(sizeof (auth_userdata));
 
1126
    if (!x) {
 
1127
        LM_ERR("error allocating mem\n");
 
1128
        goto done;
 
1129
    }
 
1130
 
 
1131
    x->private_identity.len = private_identity.len;
 
1132
    x->private_identity.s = shm_malloc(private_identity.len);
 
1133
    if (!x) {
 
1134
        LM_ERR("error allocating mem\n");
 
1135
        goto done;
 
1136
    }
 
1137
    memcpy(x->private_identity.s, private_identity.s, private_identity.len);
 
1138
 
 
1139
    x->public_identity.len = public_identity.len;
 
1140
    x->public_identity.s = shm_malloc(public_identity.len);
 
1141
    if (!x) {
 
1142
        LM_ERR("error allocating mem\n");
 
1143
        goto done;
 
1144
    }
 
1145
    memcpy(x->public_identity.s, public_identity.s, public_identity.len);
 
1146
 
 
1147
    x->head = 0;
 
1148
    x->tail = 0;
 
1149
 
 
1150
    x->next = 0;
 
1151
    x->prev = 0;
 
1152
 
 
1153
done:
 
1154
    return x;
 
1155
}
 
1156
 
 
1157
/**
 
1158
 * Deallocates the auth_userdata.
 
1159
 * @param aud - the auth_userdata to be deallocated
 
1160
 */
 
1161
void free_auth_userdata(auth_userdata * aud) {
 
1162
    auth_vector *av, *next;
 
1163
    if (aud) {
 
1164
        if (aud->private_identity.s) shm_free(aud->private_identity.s);
 
1165
        if (aud->public_identity.s) shm_free(aud->public_identity.s);
 
1166
        av = aud->head;
 
1167
        while (av) {
 
1168
            next = av->next;
 
1169
            free_auth_vector(av);
 
1170
            av = next;
 
1171
        }
 
1172
        shm_free(aud);
 
1173
    }
 
1174
}
 
1175
 
 
1176
/**
 
1177
 * Computes a hash based on the private and public identities
 
1178
 * @param private_identity - the private identity
 
1179
 * @param public_identity - the public identity
 
1180
 * @returns the hash % Auth_data->size
 
1181
 */
 
1182
inline unsigned int get_hash_auth(str private_identity, str public_identity) {
 
1183
if (av_check_only_impu)
 
1184
        return core_hash(&public_identity, 0, auth_data_hash_size);
 
1185
else
 
1186
        return core_hash(&public_identity, 0, auth_data_hash_size);
 
1187
/*
 
1188
 
 
1189
 
 
1190
#define h_inc h+=v^(v>>3)
 
1191
    char* p;
 
1192
    register unsigned v;
 
1193
    register unsigned h;
 
1194
 
 
1195
    h = 0;
 
1196
    for (p = private_identity.s; p <= (private_identity.s + private_identity.len - 4); p += 4) {
 
1197
        v = (*p << 24)+(p[1] << 16)+(p[2] << 8) + p[3];
 
1198
        h_inc;
 
1199
    }
 
1200
    v = 0;
 
1201
    for (; p < (private_identity.s + private_identity.len); p++) {
 
1202
        v <<= 8;
 
1203
        v += *p;
 
1204
    }
 
1205
    h_inc;
 
1206
    for (p = public_identity.s; p <= (public_identity.s + public_identity.len - 4); p += 4) {
 
1207
        v = (*p << 24)+(p[1] << 16)+(p[2] << 8) + p[3];
 
1208
        h_inc;
 
1209
    }
 
1210
    v = 0;
 
1211
    for (; p < (public_identity.s + public_identity.len); p++) {
 
1212
        v <<= 8;
 
1213
        v += *p;
 
1214
    }
 
1215
 
 
1216
    h = ((h)+(h >> 11))+((h >> 13)+(h >> 23));
 
1217
    return (h) % auth_data_hash_size;
 
1218
#undef h_inc
 
1219
*/
 
1220
}
 
1221
 
 
1222
/**
 
1223
 * Retrieve the auth_userdata for a user.
 
1224
 * \note you will return with lock on the hash slot, so release it!
 
1225
 * @param private_identity - the private identity
 
1226
 * @param public_identity - the public identity
 
1227
 * @returns the auth_userdata* found or newly created on success, NULL on error
 
1228
 */
 
1229
auth_userdata * get_auth_userdata(str private_identity, str public_identity) {
 
1230
 
 
1231
    unsigned int hash = 0;
 
1232
    auth_userdata *aud = 0;
 
1233
 
 
1234
    hash = get_hash_auth(private_identity, public_identity);
 
1235
    auth_data_lock(hash);
 
1236
    aud = auth_data[hash].head;
 
1237
    if (av_check_only_impu)
 
1238
      LM_DBG("Searching auth_userdata for IMPU %.*s (Hash %d)\n", public_identity.len, public_identity.s, hash);
 
1239
    else
 
1240
      LM_DBG("Searching auth_userdata for IMPU %.*s / IMPI %.*s (Hash %d)\n", public_identity.len, public_identity.s,
 
1241
        private_identity.len, private_identity.s, hash);
 
1242
 
 
1243
    while (aud) {
 
1244
        if (av_check_only_impu) {
 
1245
                if (aud->public_identity.len == public_identity.len &&
 
1246
                        memcmp(aud->public_identity.s, public_identity.s, public_identity.len) == 0) {
 
1247
                    LM_DBG("Found auth_userdata\n");
 
1248
                    return aud;
 
1249
                }
 
1250
        } else {
 
1251
                if (aud->private_identity.len == private_identity.len &&
 
1252
                        aud->public_identity.len == public_identity.len &&
 
1253
                        memcmp(aud->private_identity.s, private_identity.s, private_identity.len) == 0 &&
 
1254
                        memcmp(aud->public_identity.s, public_identity.s, public_identity.len) == 0) {
 
1255
                    LM_DBG("Found auth_userdata\n");
 
1256
                    return aud;
 
1257
                }
 
1258
        }
 
1259
 
 
1260
        aud = aud->next;
 
1261
    }
 
1262
    /* if we get here, there is no auth_userdata for this user */
 
1263
    aud = new_auth_userdata(private_identity, public_identity);
 
1264
    if (!aud) {
 
1265
        auth_data_unlock(hash);
 
1266
        return 0;
 
1267
    }
 
1268
 
 
1269
    aud->prev = auth_data[hash].tail;
 
1270
    aud->next = 0;
 
1271
    aud->hash = hash;
 
1272
 
 
1273
    if (!auth_data[hash].head) auth_data[hash].head = aud;
 
1274
    if (auth_data[hash].tail) auth_data[hash].tail->next = aud;
 
1275
    auth_data[hash].tail = aud;
 
1276
 
 
1277
    return aud;
 
1278
}
 
1279
 
 
1280
/**
 
1281
 * Sends a Multimedia-Authentication-Response to retrieve some authentication vectors and maybe synchronize.
 
1282
 * Must respond with a SIP reply every time it returns 0
 
1283
 * @param msg - the SIP REGISTER message
 
1284
 * @param public_identity - the public identity
 
1285
 * @param private_identity - the private identity
 
1286
 * @param count - how many vectors to request
 
1287
 * @param algorithm - which algorithm to request
 
1288
 * @param nonce - the challenge that will be sent
 
1289
 * @param auts - the AKA synchronization or empty string if not a synchronization
 
1290
 * @param server_name - the S-CSCF name to be saved on the HSS
 
1291
 * @returns 1 on success, 0 on failure
 
1292
 */
 
1293
int multimedia_auth_request(struct sip_msg *msg, str public_identity, str private_identity,
 
1294
        int count, str auth_scheme, str nonce, str auts, str servername, saved_transaction_t* transaction_data) {
 
1295
 
 
1296
 
 
1297
    str authorization = {0, 0};
 
1298
    int result = -1;
 
1299
 
 
1300
    //TODO this is MAR syncing - have removed it currently - TOD maybe put back in
 
1301
    //int is_sync = 0;
 
1302
//    if (auts.len) {
 
1303
//        authorization.s = pkg_malloc(nonce.len * 3 / 4 + auts.len * 3 / 4 + 8);
 
1304
//        if (!authorization.s) goto done;
 
1305
//        authorization.len = base64_to_bin(nonce.s, nonce.len, authorization.s);
 
1306
//        authorization.len = RAND_LEN;
 
1307
//        authorization.len += base64_to_bin(auts.s, auts.len, authorization.s + authorization.len);
 
1308
//        is_sync = 1;
 
1309
//    }
 
1310
 
 
1311
 
 
1312
    LM_DBG("Sending MAR\n");
 
1313
    result = cxdx_send_mar(msg, public_identity, private_identity, count, auth_scheme, authorization, servername, transaction_data);
 
1314
    if (authorization.s) pkg_free(authorization.s);
 
1315
 
 
1316
    //TODO this is MAR syncing - have removed it currently - TOD maybe put back in
 
1317
    //if (is_sync)
 
1318
    //    drop_auth_userdata(private_identity, public_identity);
 
1319
 
 
1320
    return result;
 
1321
}
 
1322
 
 
1323
/**
 
1324
 * Adds the WWW-Authenticate header for challenge, based on the authentication vector.
 
1325
 * @param msg - SIP message to add the header to
 
1326
 * @param realm - the realm
 
1327
 * @param av - the authentication vector
 
1328
 * @returns 1 on success, 0 on error
 
1329
 */
 
1330
int pack_challenge(struct sip_msg *msg, str realm, auth_vector *av, int is_proxy_auth) {
 
1331
    str x = {0, 0};
 
1332
    char ck[32], ik[32];
 
1333
    int ck_len, ik_len;
 
1334
    str *auth_prefix = is_proxy_auth ? &S_Proxy : &S_WWW;
 
1335
    switch (av->type) {
 
1336
        case AUTH_AKAV1_MD5:
 
1337
        case AUTH_AKAV2_MD5:
 
1338
            /* AKA */
 
1339
            ck_len = bin_to_base16(av->ck.s, 16, ck);
 
1340
            ik_len = bin_to_base16(av->ik.s, 16, ik);
 
1341
            x.len = S_Authorization_AKA.len + auth_prefix->len + realm.len + av->authenticate.len
 
1342
                    + algorithm_types[av->type].len + ck_len + ik_len
 
1343
                    + registration_qop_str.len;
 
1344
            x.s = pkg_malloc(x.len);
 
1345
            if (!x.s) {
 
1346
                LM_ERR("Error allocating %d bytes\n",
 
1347
                        x.len);
 
1348
                goto error;
 
1349
            }
 
1350
            sprintf(x.s, S_Authorization_AKA.s, auth_prefix->len, auth_prefix->s, realm.len, realm.s,
 
1351
                    av->authenticate.len, av->authenticate.s,
 
1352
                    algorithm_types[av->type].len, algorithm_types[av->type].s,
 
1353
                    ck_len, ck, ik_len, ik, registration_qop_str.len,
 
1354
                    registration_qop_str.s);
 
1355
            x.len = strlen(x.s);
 
1356
            break;
 
1357
        case AUTH_HTTP_DIGEST_MD5:
 
1358
            /* ETSI HTTP_DIGEST MD5 */
 
1359
            /* this one continues into the next one */
 
1360
        case AUTH_DIGEST:
 
1361
            /* Cable-Labs MD5 */
 
1362
            /* this one continues into the next one */
 
1363
        case AUTH_SIP_DIGEST:
 
1364
            /* 3GPP MD5 */
 
1365
            /* this one continues into the next one */
 
1366
        case AUTH_MD5:
 
1367
            /* FOKUS MD5 */
 
1368
            x.len = S_Authorization_MD5.len + auth_prefix->len + realm.len + av->authenticate.len
 
1369
                    + algorithm_types[av->type].len + registration_qop_str.len;
 
1370
            x.s = pkg_malloc(x.len);
 
1371
            if (!x.s) {
 
1372
                LM_ERR("pack_challenge: Error allocating %d bytes\n", x.len);
 
1373
                goto error;
 
1374
            }
 
1375
            sprintf(x.s, S_Authorization_MD5.s, auth_prefix->len, auth_prefix->s, realm.len, realm.s,
 
1376
                    av->authenticate.len, av->authenticate.s,
 
1377
                    algorithm_types[AUTH_MD5].len, algorithm_types[AUTH_MD5].s,
 
1378
                    registration_qop_str.len, registration_qop_str.s);
 
1379
            x.len = strlen(x.s);
 
1380
            break;
 
1381
 
 
1382
        default:
 
1383
            LM_CRIT("not implemented for algorithm %.*s\n",
 
1384
                    algorithm_types[av->type].len, algorithm_types[av->type].s);
 
1385
            goto error;
 
1386
    }
 
1387
 
 
1388
    if (ims_add_header_rpl(msg, &x)) {
 
1389
        pkg_free(x.s);
 
1390
        return 1;
 
1391
    }
 
1392
 
 
1393
error:
 
1394
    if (x.s)
 
1395
        pkg_free(x.s);
 
1396
 
 
1397
    return 0;
 
1398
}
 
1399
 
 
1400
/**
 
1401
 * Adds the Authentication-Info header for, based on the credentials sent by a successful REGISTER.
 
1402
 * @param msg - SIP message to add the header to
 
1403
 * @returns 1 on success, 0 on error
 
1404
 */
 
1405
int add_authinfo_resp_hdr(struct sip_msg *msg, str nextnonce, str qop, HASHHEX rspauth, str cnonce, str nc) {
 
1406
 
 
1407
    str authinfo_hdr;
 
1408
    static const char authinfo_fmt[] = "Authentication-Info: "
 
1409
            "nextnonce=\"%.*s\","
 
1410
            "qop=%.*s,"
 
1411
            "rspauth=\"%.*s\","
 
1412
            "cnonce=\"%.*s\","
 
1413
            "nc=%.*s\r\n";
 
1414
 
 
1415
    authinfo_hdr.len = sizeof (authinfo_fmt) + nextnonce.len + qop.len + HASHHEXLEN + cnonce.len + nc.len - 20 /* format string parameters */ - 1 /* trailing \0 */;
 
1416
    authinfo_hdr.s = pkg_malloc(authinfo_hdr.len + 1);
 
1417
 
 
1418
    if (!authinfo_hdr.s) {
 
1419
        LM_ERR("add_authinfo_resp_hdr: Error allocating %d bytes\n", authinfo_hdr.len);
 
1420
        goto error;
 
1421
    }
 
1422
    snprintf(authinfo_hdr.s, authinfo_hdr.len + 1, authinfo_fmt,
 
1423
            nextnonce.len, nextnonce.s,
 
1424
            qop.len, qop.s,
 
1425
            HASHHEXLEN, rspauth,
 
1426
            cnonce.len, cnonce.s,
 
1427
            nc.len, nc.s);
 
1428
    LM_DBG("authinfo hdr built: %.*s", authinfo_hdr.len, authinfo_hdr.s);
 
1429
    if (ims_add_header_rpl(msg, &authinfo_hdr)) {
 
1430
        LM_DBG("authinfo hdr added");
 
1431
        pkg_free(authinfo_hdr.s);
 
1432
        return 1;
 
1433
    }
 
1434
error:
 
1435
    if (authinfo_hdr.s) pkg_free(authinfo_hdr.s);
 
1436
 
 
1437
    return 0;
 
1438
}
 
1439
 
 
1440
/**
 
1441
 * Add an authentication vector to the authentication userdata storage.
 
1442
 * @param private_identity - the private identity
 
1443
 * @param public_identity - the public identity
 
1444
 * @param av - the authentication vector
 
1445
 * @returns 1 on success or 0 on error
 
1446
 */
 
1447
int add_auth_vector(str private_identity, str public_identity, auth_vector * av) {
 
1448
    auth_userdata *aud;
 
1449
    aud = get_auth_userdata(private_identity, public_identity);
 
1450
    if (!aud) goto error;
 
1451
 
 
1452
     LM_DBG("Adding auth_vector (status %d) for IMPU %.*s / IMPI %.*s (Hash %d)\n", av->status,
 
1453
        public_identity.len, public_identity.s,
 
1454
        private_identity.len, private_identity.s, aud->hash);
 
1455
 
 
1456
 
 
1457
    av->prev = aud->tail;
 
1458
    av->next = 0;
 
1459
 
 
1460
    if (!aud->head) aud->head = av;
 
1461
    if (aud->tail) aud->tail->next = av;
 
1462
    aud->tail = av;
 
1463
 
 
1464
    auth_data_unlock(aud->hash);
 
1465
    return 1;
 
1466
error:
 
1467
 
 
1468
    return 0;
 
1469
}
 
1470
 
 
1471
/**
 
1472
 * Declares all auth vectors as useless when we do a synchronization
 
1473
 * @param private_identity - the private identity
 
1474
 * @param public_identity - the public identity
 
1475
 * @returns 1 on sucess, 0 on error
 
1476
 */
 
1477
int drop_auth_userdata(str private_identity, str public_identity) {
 
1478
    auth_userdata *aud;
 
1479
    auth_vector *av;
 
1480
    aud = get_auth_userdata(private_identity, public_identity);
 
1481
    if (!aud) goto error;
 
1482
 
 
1483
    av = aud->head;
 
1484
    while (av) {
 
1485
        av->status = AUTH_VECTOR_USELESS;
 
1486
        av = av->next;
 
1487
    }
 
1488
    auth_data_unlock(aud->hash);
 
1489
    return 1;
 
1490
error:
 
1491
    if (aud) auth_data_unlock(aud->hash);
 
1492
    return 0;
 
1493
}