/* eXosip - This is the eXtended osip library. Copyright (C) 2002,2003,2004,2005 Aymeric MOIZARD - jack@atosc.org eXosip is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. eXosip is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifdef ENABLE_MPATROL #include #endif #include "eXosip2.h" #include #ifndef WIN32 #include #include #include #include #include #endif /* Private functions */ static jauthinfo_t *eXosip_find_authentication_info (const char *username, const char *realm); eXosip_t eXosip; void __eXosip_wakeup (void) { jpipe_write (eXosip.j_socketctl, "w", 1); } void __eXosip_wakeup_event (void) { jpipe_write (eXosip.j_socketctl_event, "w", 1); } int eXosip_lock (void) { return osip_mutex_lock ((struct osip_mutex *) eXosip.j_mutexlock); } int eXosip_unlock (void) { return osip_mutex_unlock ((struct osip_mutex *) eXosip.j_mutexlock); } int _eXosip_transaction_init (osip_transaction_t ** transaction, osip_fsm_type_t ctx_type, osip_t * osip, osip_message_t * message) { #ifdef SRV_RECORD osip_srv_record_t record; #endif int i; i = osip_transaction_init (transaction, ctx_type, osip, message); if (i != 0) { return i; } #ifdef SRV_RECORD i = _eXosip_srv_lookup(*transaction, message, &record); if (i<0) { return 0; } osip_transaction_set_srv_record(*transaction, &record); #endif return 0; } int eXosip_transaction_find (int tid, osip_transaction_t ** transaction) { int pos = 0; *transaction = NULL; while (!osip_list_eol (eXosip.j_transactions, pos)) { osip_transaction_t *tr; tr = (osip_transaction_t *) osip_list_get (eXosip.j_transactions, pos); if (tr->transactionid == tid) { *transaction = tr; return 0; } pos++; } return -1; } static int _eXosip_retry_with_auth (eXosip_dialog_t * jd, osip_transaction_t ** ptr, int *retry) { osip_transaction_t *out_tr = NULL; osip_transaction_t *tr = NULL; osip_message_t *msg = NULL; osip_event_t *sipevent; jinfo_t *ji = NULL; int cseq; osip_via_t *via; int i; if (!ptr) return -1; if (jd != NULL) { if (jd->d_out_trs == NULL) return -1; } out_tr = *ptr; if (out_tr == NULL || out_tr->orig_request == NULL || out_tr->last_response == NULL) return -1; if (retry && (*retry >= 3)) return -1; osip_message_clone (out_tr->orig_request, &msg); if (msg == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: could not clone msg for authentication\n")); return -1; } via = (osip_via_t *) osip_list_get (&msg->vias, 0); if (via == NULL || msg->cseq == NULL || msg->cseq->number == NULL) { osip_message_free (msg); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: missing via or cseq header\n")); return -1; } /* increment cseq */ cseq = atoi (msg->cseq->number); osip_free (msg->cseq->number); msg->cseq->number = strdup_printf ("%i", cseq + 1); if (jd != NULL && jd->d_dialog != NULL) { jd->d_dialog->local_cseq++; } i = eXosip_update_top_via(msg); if (i!=0) { osip_message_free (msg); OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: unsupported protocol\n")); return -1; } if (eXosip_add_authentication_information (msg, out_tr->last_response) < 0) { osip_message_free (msg); return -1; } osip_message_force_update (msg); if (MSG_IS_INVITE (msg)) i = _eXosip_transaction_init (&tr, ICT, eXosip.j_osip, msg); else i = _eXosip_transaction_init (&tr, NICT, eXosip.j_osip, msg); if (i != 0) { osip_message_free (msg); return -1; } /* replace with the new tr */ if (MSG_IS_PUBLISH(msg)) { /* old transaction is put in the garbage list */ osip_list_add (eXosip.j_transactions, out_tr, 0); /* new transaction is put in the publish context */ *ptr = tr; } else osip_list_add (eXosip.j_transactions, tr, 0); sipevent = osip_new_outgoing_sipmessage (msg); ji = osip_transaction_get_your_instance (out_tr); osip_transaction_set_your_instance (out_tr, NULL); osip_transaction_set_your_instance (tr, ji); osip_transaction_add_event (tr, sipevent); if (retry) (*retry)++; eXosip_update (); /* fixed? */ __eXosip_wakeup (); return 0; } static int _eXosip_retry_register_with_auth (eXosip_event_t * je) { eXosip_reg_t *jr = NULL; if (eXosip_reg_find_id (&jr, je->rid) < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: registration not found\n")); return -1; } if (jr->r_retry < 3) { jr->r_retry++; return eXosip_register_send_register (jr->r_id, NULL); } return -1; } static int _eXosip_retry_invite_with_auth (eXosip_event_t * je) { eXosip_dialog_t *jd = NULL; eXosip_call_t *jc = NULL; int *retry = NULL; osip_transaction_t *tr=NULL; _eXosip_call_transaction_find (je->tid, &jc, &jd, &tr); if (jc==NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: call dialog not found\n")); return -1; } if (jd && jd->d_dialog) retry = &jd->d_retry; else retry = &jc->c_retry; if (*retry < 3) { (*retry)++; return _eXosip_call_send_request_with_credential(jc, jd, tr); } return -1; } static int _eXosip_redirect_invite (eXosip_event_t * je) { eXosip_dialog_t *jd = NULL; eXosip_call_t *jc = NULL; osip_transaction_t *tr=NULL; _eXosip_call_transaction_find (je->tid, &jc, &jd, &tr); if (jc==NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: call dialog not found\n")); return -1; } return _eXosip_call_redirect_request (jc, jd, tr); } static int _eXosip_retry_subscribe_with_auth (eXosip_event_t * je) { eXosip_dialog_t *jd = NULL; eXosip_subscribe_t *js = NULL; int *retry = NULL; osip_transaction_t *tr=NULL; if (_eXosip_subscribe_transaction_find (je->tid, &js, &jd, &tr) < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: subscribe dialog not found\n")); return -1; } if (jd && jd->d_dialog) retry = &jd->d_retry; else retry = &js->s_retry; if (*retry < 3) { (*retry)++; return _eXosip_subscribe_send_request_with_credential(js, jd, tr); } return -1; } static int _eXosip_retry_publish_with_auth (eXosip_event_t * je) { eXosip_pub_t *jp = NULL; if (_eXosip_pub_find_by_tid (&jp, je->tid) < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: publish transaction not found\n")); return -1; } return _eXosip_retry_with_auth (NULL, &jp->p_last_tr, NULL); } static int _eXosip_retry_notify_with_auth (eXosip_event_t * je) { /* TODO untested */ eXosip_dialog_t *jd = NULL; eXosip_notify_t *jn = NULL; osip_transaction_t *tr=NULL; if (_eXosip_insubscription_transaction_find (je->tid, &jn, &jd, &tr) < 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: notify dialog not found\n")); return -1; } return _eXosip_insubscription_send_request_with_credential (jn, jd, tr); } static int eXosip_retry_with_auth (eXosip_event_t * je) { if (!je || !je->request || !je->response) return -1; if (je->rid>0) { return _eXosip_retry_register_with_auth (je); } else if (je->cid>0) { return _eXosip_retry_invite_with_auth (je); } else if (je->sid>0) { return _eXosip_retry_subscribe_with_auth (je); } else if (je->nid>0) { return _eXosip_retry_notify_with_auth (je); } else if (MSG_IS_PUBLISH (je->request)) return _eXosip_retry_publish_with_auth (je); else { osip_transaction_t *tr=NULL; eXosip_transaction_find(je->tid, &tr); if (tr!=NULL) { return _eXosip_retry_with_auth (NULL, &tr, NULL); } } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Can't retry event %d with auth\n", je->type)); return -1; } static int _eXosip_redirect (eXosip_event_t * je) { switch (je->type) { case EXOSIP_CALL_REDIRECTED: return _eXosip_redirect_invite (je); case EXOSIP_CALL_MESSAGE_REDIRECTED: case EXOSIP_MESSAGE_REDIRECTED: case EXOSIP_SUBSCRIPTION_REDIRECTED: OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: not implemented\n")); return -1; default: OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Can't redirect event %d\n", je->type)); return -1; } } int eXosip_default_action (eXosip_event_t * je) { if (!je || !je->response) return -1; if (je->response->status_code == 401 || je->response->status_code == 407) return eXosip_retry_with_auth (je); else if (je->response->status_code >= 300 && je->response->status_code <= 399) return _eXosip_redirect (je); else return 1; } void eXosip_automatic_refresh (void) { eXosip_subscribe_t *js; eXosip_dialog_t *jd; eXosip_reg_t *jr; time_t now; now = time (NULL); for (js = eXosip.j_subscribes; js != NULL; js = js->next) { for (jd = js->s_dialogs; jd != NULL; jd = jd->next) { if (jd->d_dialog != NULL && (jd->d_id >= 1)) /* finished call */ { osip_transaction_t *out_tr = NULL; out_tr = osip_list_get (jd->d_out_trs, 0); if (out_tr == NULL) out_tr = js->s_out_tr; if (js->s_reg_period == 0 || out_tr == NULL) { } else if (now - out_tr->birth_time > js->s_reg_period - 60) { /* will expires in 60 sec: send refresh! */ int i; i = _eXosip_subscribe_send_request_with_credential (js, jd, out_tr); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: could not clone subscribe for refresh\n")); } } } } } for (jr = eXosip.j_reg; jr != NULL; jr = jr->next) { if (jr->r_id >= 1 && jr->r_last_tr != NULL) { if (jr->r_reg_period == 0) { /* skip refresh! */ } else if (now - jr->r_last_tr->birth_time > 900) { /* automatic refresh */ eXosip_register_send_register (jr->r_id, NULL); } else if (now - jr->r_last_tr->birth_time > jr->r_reg_period - 60) { /* automatic refresh */ eXosip_register_send_register (jr->r_id, NULL); } else if (now - jr->r_last_tr->birth_time > 120 && (jr->r_last_tr->last_response == NULL || (!MSG_IS_STATUS_2XX (jr->r_last_tr->last_response)))) { /* automatic refresh */ eXosip_register_send_register (jr->r_id, NULL); } } } } void eXosip_retransmit_lost200ok() { eXosip_call_t *jc; eXosip_dialog_t *jd; time_t now; now = time (NULL); for (jc = eXosip.j_calls; jc != NULL; jc = jc->next) { if (jc->c_id >= 1 && jc->c_dialogs != NULL) { for (jd = jc->c_dialogs; jd != NULL; jd = jd->next) { if (jd->d_id >=1 && jd->d_dialog != NULL && jd->d_200Ok!=NULL) { if (jd->d_count==5) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: no ACK received during 20s: dropping call\n")); /* hard for users to detect than I sent this BYE... */ jd->d_count=0; osip_message_free(jd->d_200Ok); jd->d_200Ok=NULL; eXosip_call_terminate(jc->c_id, jd->d_id); } else if (jd->d_timerd_timer = time (NULL) + 4; jd->d_count++; jd = jc->c_dialogs; /* TU retransmission */ cb_snd_message (NULL, jd->d_200Ok, NULL,0, -1); } } } } } return; } void eXosip_automatic_action (void) { eXosip_call_t *jc; eXosip_subscribe_t *js; eXosip_dialog_t *jd; eXosip_notify_t *jn; eXosip_reg_t *jr; time_t now; now = time (NULL); for (jc = eXosip.j_calls; jc != NULL; jc = jc->next) { if (jc->c_id < 1) { } else if (jc->c_dialogs == NULL || jc->c_dialogs->d_dialog == NULL) { /* an EARLY dialog may have failed with 401,407 or 3Xx */ osip_transaction_t *out_tr = NULL; out_tr = jc->c_out_tr; if (out_tr != NULL && (out_tr->state == ICT_TERMINATED || out_tr->state == NICT_TERMINATED || out_tr->state == ICT_COMPLETED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < 120 && out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407)) { /* retry with credential */ if (jc->c_retry < 3) { int i; i = _eXosip_call_send_request_with_credential (jc, NULL, out_tr); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: could not clone msg for authentication\n")); } jc->c_retry++; } } else if (out_tr != NULL && (out_tr->state == ICT_TERMINATED || out_tr->state == NICT_TERMINATED || out_tr->state == ICT_COMPLETED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < 120 && out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code >= 300 && out_tr->last_response->status_code <= 399)) { /* retry with credential */ int i; i = _eXosip_call_redirect_request (jc, NULL, out_tr); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: could not clone msg for redirection\n")); } } } for (jd = jc->c_dialogs; jd != NULL; jd = jd->next) { if (jd->d_dialog == NULL) /* finished call */ { } else { osip_transaction_t *out_tr = NULL; out_tr = osip_list_get (jd->d_out_trs, 0); if (out_tr == NULL) out_tr = jc->c_out_tr; if (out_tr != NULL && (out_tr->state == ICT_TERMINATED || out_tr->state == NICT_TERMINATED || out_tr->state == ICT_COMPLETED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < 120 && out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407)) { /* retry with credential */ if (jd->d_retry < 3) { int i; i = _eXosip_call_send_request_with_credential (jc, jd, out_tr); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: could not clone msg for authentication\n")); } jd->d_retry++; } } else if (out_tr != NULL && (out_tr->state == ICT_TERMINATED || out_tr->state == NICT_TERMINATED || out_tr->state == ICT_COMPLETED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < 120 && out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code >= 300 && out_tr->last_response->status_code <= 399)) { /* retry with credential */ int i; i = _eXosip_call_redirect_request (jc, jd, out_tr); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: could not clone msg for redirection\n")); } } } } } for (js = eXosip.j_subscribes; js != NULL; js = js->next) { if (js->s_id < 1) { } else if (js->s_dialogs == NULL) { osip_transaction_t *out_tr = NULL; out_tr = js->s_out_tr; if (out_tr != NULL && (out_tr->state == NICT_TERMINATED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < 120 && out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407)) { /* retry with credential */ if (js->s_retry < 3) { int i; i = _eXosip_subscribe_send_request_with_credential (js, NULL, out_tr); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: could not clone msg for authentication\n")); } js->s_retry++; } } } for (jd = js->s_dialogs; jd != NULL; jd = jd->next) { if (jd->d_dialog != NULL) /* finished call */ { if (jd->d_id >= 1) { osip_transaction_t *out_tr = NULL; out_tr = osip_list_get (jd->d_out_trs, 0); if (out_tr == NULL) out_tr = js->s_out_tr; if (out_tr != NULL && (out_tr->state == NICT_TERMINATED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < 120 && out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407)) { /* retry with credential */ if (jd->d_retry < 3) { int i; i = _eXosip_subscribe_send_request_with_credential (js, jd, out_tr); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: could not clone suscbribe for authentication\n")); } jd->d_retry++; } } else if (js->s_reg_period == 0 || out_tr == NULL) { } else if (now - out_tr->birth_time > js->s_reg_period - 60) { /* will expires in 60 sec: send refresh! */ int i; i = _eXosip_subscribe_send_request_with_credential (js, jd, out_tr); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: could not clone subscribe for refresh\n")); } } } } } } for (jn = eXosip.j_notifies; jn != NULL; jn = jn->next) { for (jd = jn->n_dialogs; jd != NULL; jd = jd->next) { if (jd->d_dialog != NULL) /* finished call */ { if (jd->d_id >= 1) { osip_transaction_t *out_tr = NULL; out_tr = osip_list_get (jd->d_out_trs, 0); if (out_tr != NULL && (out_tr->state == NICT_TERMINATED || out_tr->state == NICT_COMPLETED) && now - out_tr->birth_time < 120 && out_tr->orig_request != NULL && out_tr->last_response != NULL && (out_tr->last_response->status_code == 401 || out_tr->last_response->status_code == 407)) { /* retry with credential */ if (jd->d_retry < 3) { int i; i = _eXosip_insubscription_send_request_with_credential (jn, jd, out_tr); if (i != 0) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: could not clone notify for authentication\n")); } jd->d_retry++; } } } } } } for (jr = eXosip.j_reg; jr != NULL; jr = jr->next) { if (jr->r_id >= 1 && jr->r_last_tr != NULL) { if (jr->r_reg_period != 0 && now - jr->r_last_tr->birth_time > 900) { /* automatic refresh */ eXosip_register_send_register (jr->r_id, NULL); } else if (jr->r_reg_period != 0 && now - jr->r_last_tr->birth_time > jr->r_reg_period - 60) { /* automatic refresh */ eXosip_register_send_register (jr->r_id, NULL); } else if (jr->r_reg_period != 0 && now - jr->r_last_tr->birth_time > 120 && (jr->r_last_tr->last_response == NULL || (!MSG_IS_STATUS_2XX (jr->r_last_tr->last_response)))) { /* automatic refresh */ eXosip_register_send_register (jr->r_id, NULL); } else if (now - jr->r_last_tr->birth_time < 120 && jr->r_last_tr->orig_request != NULL && (jr->r_last_tr->last_response != NULL && (jr->r_last_tr->last_response->status_code == 401 || jr->r_last_tr->last_response->status_code == 407))) { if (jr->r_retry < 3) { /* TODO: improve support for several retries when several credentials are needed */ eXosip_register_send_register (jr->r_id, NULL); jr->r_retry++; } } } } } void eXosip_update () { static int static_id = 1; eXosip_call_t *jc; eXosip_subscribe_t *js; eXosip_notify_t *jn; eXosip_dialog_t *jd; time_t now; if (static_id > 100000) static_id = 1; /* loop */ now = time (NULL); for (jc = eXosip.j_calls; jc != NULL; jc = jc->next) { if (jc->c_id < 1) { jc->c_id = static_id; static_id++; } for (jd = jc->c_dialogs; jd != NULL; jd = jd->next) { if (jd->d_dialog != NULL) /* finished call */ { if (jd->d_id < 1) { jd->d_id = static_id; static_id++; } } else jd->d_id = -1; } } for (js = eXosip.j_subscribes; js != NULL; js = js->next) { if (js->s_id < 1) { js->s_id = static_id; static_id++; } for (jd = js->s_dialogs; jd != NULL; jd = jd->next) { if (jd->d_dialog != NULL) /* finished call */ { if (jd->d_id < 1) { jd->d_id = static_id; static_id++; } } else jd->d_id = -1; } } for (jn = eXosip.j_notifies; jn != NULL; jn = jn->next) { if (jn->n_id < 1) { jn->n_id = static_id; static_id++; } for (jd = jn->n_dialogs; jd != NULL; jd = jd->next) { if (jd->d_dialog != NULL) /* finished call */ { if (jd->d_id < 1) { jd->d_id = static_id; static_id++; } } else jd->d_id = -1; } } } static jauthinfo_t * eXosip_find_authentication_info (const char *username, const char *realm) { jauthinfo_t *fallback = NULL; jauthinfo_t *authinfo; for (authinfo = eXosip.authinfos; authinfo != NULL; authinfo = authinfo->next) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "INFO: authinfo: %s %s\n", realm, authinfo->realm)); if (0 == strcmp (authinfo->username, username)) { if (authinfo->realm == NULL || authinfo->realm[0] == '\0') { fallback = authinfo; } else if (strcmp (realm, authinfo->realm) == 0 || 0 == strncmp (realm + 1, authinfo->realm, strlen (realm) - 2)) { return authinfo; } } } /* no matching username has been found for this realm, try with another username... */ for (authinfo = eXosip.authinfos; authinfo != NULL; authinfo = authinfo->next) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "INFO: authinfo: %s %s\n", realm, authinfo->realm)); if (authinfo->realm == NULL || authinfo->realm[0] == '\0') { fallback = authinfo; } else if (strcmp (realm, authinfo->realm) == 0 || 0 == strncmp (realm + 1, authinfo->realm, strlen (realm) - 2)) { return authinfo; } } return fallback; } int eXosip_clear_authentication_info () { jauthinfo_t *jauthinfo; for (jauthinfo = eXosip.authinfos; jauthinfo != NULL; jauthinfo = eXosip.authinfos) { REMOVE_ELEMENT (eXosip.authinfos, jauthinfo); osip_free (jauthinfo); } return 0; } int eXosip_add_authentication_info (const char *username, const char *userid, const char *passwd, const char *ha1, const char *realm) { jauthinfo_t *authinfos; if (username == NULL || username[0] == '\0') return -1; if (userid == NULL || userid[0] == '\0') return -1; if (passwd != NULL && passwd[0] != '\0') { } else if (ha1 != NULL && ha1[0] != '\0') { } else return -1; authinfos = (jauthinfo_t *) osip_malloc (sizeof (jauthinfo_t)); if (authinfos == NULL) return -1; memset (authinfos, 0, sizeof (jauthinfo_t)); snprintf (authinfos->username, 50, "%s", username); snprintf (authinfos->userid, 50, "%s", userid); if (passwd != NULL && passwd[0] != '\0') snprintf (authinfos->passwd, 50, "%s", passwd); else if (ha1 != NULL && ha1[0] != '\0') snprintf (authinfos->ha1, 50, "%s", ha1); if (realm != NULL && realm[0] != '\0') snprintf (authinfos->realm, 50, "%s", realm); ADD_ELEMENT (eXosip.authinfos, authinfos); return 0; } int eXosip_add_authentication_information (osip_message_t * req, osip_message_t * last_response) { osip_authorization_t *aut = NULL; osip_www_authenticate_t *wwwauth = NULL; osip_proxy_authorization_t *proxy_aut = NULL; osip_proxy_authenticate_t *proxyauth = NULL; jauthinfo_t *authinfo = NULL; int pos; int i; if (req == NULL || req->from == NULL || req->from->url == NULL || req->from->url->username == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "authinfo: Invalid message\n")); return -1; } pos = 0; osip_message_get_www_authenticate (last_response, pos, &wwwauth); osip_message_get_proxy_authenticate (last_response, pos, &proxyauth); if (wwwauth == NULL && proxyauth == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "authinfo: No WWW-Authenticate or Proxy-Authenticate\n")); return -1; } while (wwwauth != NULL) { char *uri; authinfo = eXosip_find_authentication_info (req->from->url->username, wwwauth->realm); if (authinfo == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "authinfo: No authentication found for %s %s\n", req->from->url->username, wwwauth->realm)); return -1; } i = osip_uri_to_str (req->req_uri, &uri); if (i != 0) return -1; i = __eXosip_create_authorization_header (last_response, uri, authinfo->userid, authinfo->passwd, authinfo->ha1, &aut, req->sip_method); osip_free (uri); if (i != 0) return -1; if (aut != NULL) { osip_list_add (&req->authorizations, aut, -1); osip_message_force_update (req); } pos++; osip_message_get_www_authenticate (last_response, pos, &wwwauth); } pos = 0; while (proxyauth != NULL) { char *uri; authinfo = eXosip_find_authentication_info (req->from->url->username, proxyauth->realm); if (authinfo == NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO2, NULL, "authinfo: No authentication found for %s %s\n", req->from->url->username, proxyauth->realm)); return -1; } OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "authinfo: %s\n", authinfo->username)); i = osip_uri_to_str (req->req_uri, &uri); if (i != 0) return -1; i = __eXosip_create_proxy_authorization_header (last_response, uri, authinfo->userid, authinfo->passwd, authinfo->ha1, &proxy_aut, req->sip_method); osip_free (uri); if (i != 0) return -1; if (proxy_aut != NULL) { osip_list_add (&req->proxy_authorizations, proxy_aut, -1); osip_message_force_update (req); } pos++; osip_message_get_proxy_authenticate (last_response, pos, &proxyauth); } return 0; } int eXosip_update_top_via (osip_message_t * sip) { unsigned int number; char tmp[40]; osip_generic_param_t *br=NULL; osip_via_t *via = (osip_via_t *) osip_list_get (&sip->vias, 0); if (via==NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "missing via in SIP message\n")); return -1; } /* browse parameter and replace "branch" */ osip_via_param_get_byname (via, "branch", &br); if (br==NULL || br->gvalue==NULL) { OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "missing branch parameter via in SIP message\n")); return -1; } osip_free(br->gvalue); number = osip_build_random_number (); sprintf (tmp, "z9hG4bK%u", number); br->gvalue = osip_strdup(tmp); return 0; }