--- asterisk-1.8.0-beta4.orig/channels/chan_sip.c 2011-02-03 09:02:54.275609994 +0100 +++ asterisk-1.8.0-beta4/channels/chan_sip.c 2011-02-03 09:13:10.087610005 +0100 @@ -1306,6 +1306,7 @@ int sipmethod, const char *uri, enum xmittype reliable, struct ast_sockaddr *addr, struct sip_peer **authpeer); static int check_user(struct sip_pvt *p, struct sip_request *req, int sipmethod, const char *uri, enum xmittype reliable, struct ast_sockaddr *addr); +static void auth_headers(enum sip_auth_type code, char **header, char **respheader); /*--- Domain handling */ static int check_sip_domain(const char *domain, char *context, size_t len); /* Check if domain is one of our local domains */ @@ -5224,6 +5225,9 @@ dialog->chanvars = copy_vars(peer->chanvars); if (peer->fromdomainport) dialog->fromdomainport = peer->fromdomainport; + dialog->noncecaching = peer->noncecaching; + return 0; } @@ -5505,7 +5509,38 @@ connected.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER; ast_channel_queue_connected_line_update(ast, &connected, &update_connected); } - + if (p->noncecaching){ + struct sip_registry *found_reg; + char digest[1024]; + char *header, *respheader; + + // recherche du reg associĆ© au peer name + found_reg = ASTOBJ_CONTAINER_FIND(®l,p->peername); + if(found_reg) { + // Copy des info de la structure registry vers la structure PVT + ast_debug(1, " >>> Re-using Auth data for %s@%s\n", found_reg->username, found_reg->hostname); + ast_string_field_set(p, realm, found_reg->realm); + ast_string_field_set(p, nonce, found_reg->nonce); + ast_string_field_set(p, domain, found_reg->authdomain); + ast_string_field_set(p, opaque, found_reg->opaque); + ast_string_field_set(p, qop, found_reg->qop); + p->noncecount = ++found_reg->noncecount; + ASTOBJ_UNREF(found_reg, sip_registry_destroy); + p->authtries++; + + auth_headers(407, &header, &respheader); + + memset(digest, 0, sizeof(digest)); + if(!build_reply_digest(p,SIP_INVITE, digest, sizeof(digest))) { + /* Now we have a reply digest */ + p->options->auth = digest; + p->options->authheader = respheader; + } else { + ast_log(LOG_NOTICE, "No authorization available for authentication of registration to %s@%s\n", found_reg->username, found_reg->hostname); + } + } + } xmitres = transmit_invite(p, SIP_INVITE, 1, 2, uri); sip_pvt_unlock(p); if (xmitres == XMIT_ERROR) @@ -7941,7 +7976,6 @@ static int sip_register(const char *value, int lineno) { struct sip_registry *reg; - if (!(reg = ast_calloc_with_stringfields(1, struct sip_registry, 256))) { ast_log(LOG_ERROR, "Out of memory. Can't allocate SIP registry entry\n"); return -1; @@ -7954,6 +7988,11 @@ registry_unref(reg, "failure to parse, unref the reg pointer"); return -1; } + ASTOBJ_WRLOCK(reg); + + ast_copy_string(reg->name, reg->peername,sizeof(reg->name)); + ASTOBJ_UNLOCK(reg); /* set default expiry if necessary */ if (reg->refresh && !reg->expiry && !reg->configured_expiry) { @@ -18541,8 +18580,22 @@ p->noncecount = 0; /* Save auth data for following registrations */ - if (p->registry) { - struct sip_registry *r = p->registry; + { + struct sip_registry *r ; + int unref = 0; + if (p->registry) { // only if register + r = p->registry; + } + else + { + // Sagem nonce caching with Invite too + if (p->noncecaching) { + r = ASTOBJ_CONTAINER_FIND(®l,p->peername); + unref = 1; + } + } + + if (r) { if (strcmp(r->nonce, p->nonce)) { ast_string_field_set(r, realm, p->realm); @@ -18551,6 +18604,8 @@ ast_string_field_set(r, opaque, p->opaque); ast_string_field_set(r, qop, p->qop); r->noncecount = 0; + if (r && unref) ASTOBJ_UNREF(r, sip_registry_destroy); + } } } return build_reply_digest(p, sipmethod, digest, digest_len); @@ -26401,6 +26456,8 @@ /* clear the transport information. We will detect if a default value is required after parsing the config */ peer->default_outbound_transport = 0; peer->transports = 0; + peer->noncecaching = 0; if (!devstate_only) { struct sip_mailbox *mailbox; @@ -26802,6 +26859,9 @@ } } else if (ast_cc_is_config_param(v->name)) { ast_cc_set_param(peer->cc_params, v->name, v->value); + } else if (!strcasecmp(v->name, "noncecaching")) { + peer->noncecaching = ast_true(v->value) ? 1 : 0; } } --- asterisk-1.8.0-beta4.orig/channels/sip/include/sip.h 2011-02-03 09:02:54.271610000 +0100 +++ asterisk-1.8.0-beta4/channels/sip/include/sip.h 2011-02-03 09:04:41.207610104 +0100 @@ -1104,6 +1104,7 @@ struct sip_pvt { struct ast_cc_config_params *cc_params; struct sip_epa_entry *epa_entry; int fromdomainport; /*!< Domain port to show in from field */ + int noncecaching; }; /*! \brief sip packet - raw format for outbound packets that are sent or scheduled for transmission @@ -1244,6 +1245,7 @@ struct sip_peer { enum sip_peer_type type; /*!< Distinguish between "user" and "peer" types. This is used solely for CLI and manager commands */ unsigned int disallowed_methods; struct ast_cc_config_params *cc_params; + int noncecaching; }; /*! @@ -1261,7 +1263,7 @@ struct sip_peer { * \todo Convert this to astobj2 */ struct sip_registry { - ASTOBJ_COMPONENTS_FULL(struct sip_registry,1,1); + ASTOBJ_COMPONENTS_FULL(struct sip_registry,50,1); AST_DECLARE_STRING_FIELDS( AST_STRING_FIELD(callid); /*!< Global Call-ID */ AST_STRING_FIELD(realm); /*!< Authorization realm */