LCOV - code coverage report
Current view: top level - media/mtransport/third_party/nICEr/src/stun - stun_proc.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 200 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             : Copyright (c) 2007, Adobe Systems, Incorporated
       3             : All rights reserved.
       4             : 
       5             : Redistribution and use in source and binary forms, with or without
       6             : modification, are permitted provided that the following conditions are
       7             : met:
       8             : 
       9             : * Redistributions of source code must retain the above copyright
      10             :   notice, this list of conditions and the following disclaimer.
      11             : 
      12             : * Redistributions in binary form must reproduce the above copyright
      13             :   notice, this list of conditions and the following disclaimer in the
      14             :   documentation and/or other materials provided with the distribution.
      15             : 
      16             : * Neither the name of Adobe Systems, Network Resonance nor the names of its
      17             :   contributors may be used to endorse or promote products derived from
      18             :   this software without specific prior written permission.
      19             : 
      20             : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21             : "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      22             : LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      23             : A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      24             : OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      25             : SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      26             : LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      27             : DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      28             : THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      29             : (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      30             : OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      31             : */
      32             : 
      33             : 
      34             : static char *RCSSTRING __UNUSED__="$Id: stun_proc.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
      35             : 
      36             : #include <errno.h>
      37             : #include <csi_platform.h>
      38             : 
      39             : #ifdef WIN32
      40             : #include <winsock2.h>
      41             : #include <stdlib.h>
      42             : #include <io.h>
      43             : #include <time.h>
      44             : #else   /* UNIX */
      45             : #include <string.h>
      46             : #endif  /* end UNIX */
      47             : #include <assert.h>
      48             : 
      49             : #include "stun.h"
      50             : #include "stun_reg.h"
      51             : #include "registry.h"
      52             : 
      53             : static int
      54             : nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res);
      55             : 
      56             : /* draft-ietf-behave-rfc3489bis-10.txt S 7.3 */
      57             : int
      58           0 : nr_stun_receive_message(nr_stun_message *req, nr_stun_message *msg)
      59             : {
      60             :     int _status;
      61             :     nr_stun_message_attribute *attr;
      62             : 
      63             : #ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
      64             :     /* if this message was generated by an RFC 3489 impementation,
      65             :      * the call to nr_is_stun_message will fail, so skip that
      66             :      * check and puke elsewhere if the message can't be decoded */
      67           0 :     if (msg->header.magic_cookie == NR_STUN_MAGIC_COOKIE
      68           0 :      || msg->header.magic_cookie == NR_STUN_MAGIC_COOKIE2) {
      69             : #endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */
      70           0 :     if (!nr_is_stun_message(msg->buffer, msg->length)) {
      71           0 :         r_log(NR_LOG_STUN, LOG_WARNING, "Not a STUN message");
      72           0 :         ABORT(R_REJECTED);
      73             :     }
      74             : #ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
      75             :     }
      76             : #endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */
      77             : 
      78           0 :     if (req == 0) {
      79           0 :         if (NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_REQUEST) {
      80           0 :             r_log(NR_LOG_STUN,LOG_WARNING,"Illegal message type: %03x", msg->header.type);
      81           0 :             ABORT(R_REJECTED);
      82             :         }
      83             :     }
      84             :     else {
      85           0 :         if (NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_RESPONSE
      86           0 :          && NR_STUN_GET_TYPE_CLASS(msg->header.type) != NR_CLASS_ERROR_RESPONSE) {
      87           0 :             r_log(NR_LOG_STUN,LOG_WARNING,"Illegal message class: %03x", msg->header.type);
      88           0 :             ABORT(R_REJECTED);
      89             :         }
      90             : 
      91           0 :         if (NR_STUN_GET_TYPE_METHOD(req->header.type) != NR_STUN_GET_TYPE_METHOD(msg->header.type)) {
      92           0 :             r_log(NR_LOG_STUN,LOG_WARNING,"Inconsistent message method: %03x expected %03x", msg->header.type, req->header.type);
      93           0 :             ABORT(R_REJECTED);
      94             :         }
      95             : 
      96           0 :         if (nr_stun_different_transaction(msg->buffer, msg->length, req)) {
      97           0 :             r_log(NR_LOG_STUN, LOG_DEBUG, "Unrecognized STUN transaction");
      98           0 :             ABORT(R_REJECTED);
      99             :         }
     100             :     }
     101             : 
     102           0 :     switch (msg->header.magic_cookie) {
     103             :     case NR_STUN_MAGIC_COOKIE:
     104             :         /* basically draft-ietf-behave-rfc3489bis-10.txt S 6 rules */
     105             : 
     106           0 :         if (nr_stun_message_has_attribute(msg, NR_STUN_ATTR_FINGERPRINT, &attr)
     107           0 :          && !attr->u.fingerprint.valid) {
     108           0 :             r_log(NR_LOG_STUN, LOG_WARNING, "Invalid fingerprint");
     109           0 :             ABORT(R_REJECTED);
     110             :         }
     111             : 
     112           0 :         break;
     113             : 
     114             : #ifdef USE_STUND_0_96
     115             :     case NR_STUN_MAGIC_COOKIE2:
     116             :         /* nothing to check in this case */
     117           0 :         break;
     118             : #endif /* USE_STUND_0_96 */
     119             : 
     120             :     default:
     121             : #ifdef USE_RFC_3489_BACKWARDS_COMPATIBLE
     122             :         /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
     123             : #else
     124             : #ifdef NDEBUG
     125             :         /* in deployment builds we should always see a recognized magic cookie */
     126             :         r_log(NR_LOG_STUN, LOG_WARNING, "Missing Magic Cookie");
     127             :         ABORT(R_REJECTED);
     128             : #else
     129             :         /* ignore this condition because sometimes we like to pretend we're
     130             :          * a server talking to old clients and their messages don't contain
     131             :          * a magic cookie at all but rather the magic cookie field is part
     132             :          * of their ID and therefore random */
     133             : #endif /* NDEBUG */
     134             : #endif /* USE_RFC_3489_BACKWARDS_COMPATIBLE */
     135           0 :         break;
     136             :     }
     137             : 
     138           0 :     _status=0;
     139             :   abort:
     140           0 :     return _status;
     141             : }
     142             : 
     143             : /* draft-ietf-behave-rfc3489bis-10.txt S 7.3.1 */
     144             : int
     145           0 : nr_stun_process_request(nr_stun_message *req, nr_stun_message *res)
     146             : {
     147             :     int _status;
     148             : #ifdef USE_STUN_PEDANTIC
     149             :     int r;
     150           0 :     nr_stun_attr_unknown_attributes unknown_attributes = { { 0 } };
     151             :     nr_stun_message_attribute *attr;
     152             : 
     153           0 :     if (req->comprehension_required_unknown_attributes > 0) {
     154           0 :         nr_stun_form_error_response(req, res, 420, "Unknown Attributes");
     155           0 :         r_log(NR_LOG_STUN, LOG_WARNING, "Request contains comprehension required but unknown attributes");
     156             : 
     157           0 :         TAILQ_FOREACH(attr, &req->attributes, entry) {
     158           0 :             if (attr->name == 0) {
     159             :                 /* unrecognized attribute */
     160             : 
     161             :                 /* should never happen, but truncate if it ever were to occur */
     162           0 :                 if (unknown_attributes.num_attributes > NR_STUN_MAX_UNKNOWN_ATTRIBUTES)
     163           0 :                     break;
     164             : 
     165           0 :                 unknown_attributes.attribute[unknown_attributes.num_attributes++] = attr->type;
     166             :             }
     167             :         }
     168             : 
     169           0 :         assert(req->comprehension_required_unknown_attributes + req->comprehension_optional_unknown_attributes == unknown_attributes.num_attributes);
     170             : 
     171           0 :         if ((r=nr_stun_message_add_unknown_attributes_attribute(res, &unknown_attributes)))
     172           0 :             ABORT(R_ALREADY);
     173             : 
     174           0 :         ABORT(R_ALREADY);
     175             :     }
     176             : #endif /* USE_STUN_PEDANTIC */
     177             : 
     178           0 :     _status=0;
     179             : #ifdef USE_STUN_PEDANTIC
     180             :   abort:
     181             : #endif /* USE_STUN_PEDANTIC */
     182           0 :     return _status;
     183             : }
     184             : 
     185             : /* draft-ietf-behave-rfc3489bis-10.txt S 7.3.2 */
     186             : int
     187           0 : nr_stun_process_indication(nr_stun_message *ind)
     188             : {
     189             :     int _status;
     190             : #ifdef USE_STUN_PEDANTIC
     191             : 
     192           0 :     if (ind->comprehension_required_unknown_attributes > 0) {
     193           0 :         r_log(NR_LOG_STUN, LOG_WARNING, "Indication contains comprehension required but unknown attributes");
     194           0 :         ABORT(R_REJECTED);
     195             :     }
     196             : #endif /* USE_STUN_PEDANTIC */
     197             : 
     198           0 :     _status=0;
     199             : #ifdef USE_STUN_PEDANTIC
     200             :   abort:
     201             : #endif /* USE_STUN_PEDANTIC */
     202           0 :     return _status;
     203             : }
     204             : 
     205             : /* RFC5389 S 7.3.3, except that we *also* allow a MAPPED_ADDRESS
     206             :    to compensate for a bug in Google's STUN server where it
     207             :    always returns MAPPED_ADDRESS.
     208             : 
     209             :    Mozilla bug: 888274.
     210             :  */
     211             : int
     212           0 : nr_stun_process_success_response(nr_stun_message *res)
     213             : {
     214             :     int _status;
     215             : 
     216             : #ifdef USE_STUN_PEDANTIC
     217           0 :     if (res->comprehension_required_unknown_attributes > 0) {
     218           0 :         r_log(NR_LOG_STUN, LOG_WARNING, "Response contains comprehension required but unknown attributes");
     219           0 :         ABORT(R_REJECTED);
     220             :     }
     221             : #endif /* USE_STUN_PEDANTIC */
     222             : 
     223           0 :     if (NR_STUN_GET_TYPE_METHOD(res->header.type) == NR_METHOD_BINDING) {
     224           0 :         if (! nr_stun_message_has_attribute(res, NR_STUN_ATTR_XOR_MAPPED_ADDRESS, 0) &&
     225           0 :             ! nr_stun_message_has_attribute(res, NR_STUN_ATTR_MAPPED_ADDRESS, 0)) {
     226           0 :             r_log(NR_LOG_STUN, LOG_WARNING, "Missing XOR-MAPPED-ADDRESS and MAPPED_ADDRESS");
     227           0 :             ABORT(R_REJECTED);
     228             :         }
     229             :     }
     230             : 
     231           0 :     _status=0;
     232             :  abort:
     233           0 :     return _status;
     234             : }
     235             : 
     236             : /* draft-ietf-behave-rfc3489bis-10.txt S 7.3.4 */
     237             : int
     238           0 : nr_stun_process_error_response(nr_stun_message *res, UINT2 *error_code)
     239             : {
     240             :     int _status;
     241             :     nr_stun_message_attribute *attr;
     242             : 
     243           0 :     if (res->comprehension_required_unknown_attributes > 0) {
     244           0 :         r_log(NR_LOG_STUN, LOG_WARNING, "Error response contains comprehension required but unknown attributes");
     245           0 :         ABORT(R_REJECTED);
     246             :     }
     247             : 
     248           0 :     if (! nr_stun_message_has_attribute(res, NR_STUN_ATTR_ERROR_CODE, &attr)) {
     249           0 :         r_log(NR_LOG_STUN, LOG_WARNING, "Missing ERROR-CODE");
     250           0 :         ABORT(R_REJECTED);
     251             :     }
     252             : 
     253           0 :     *error_code = attr->u.error_code.number;
     254             : 
     255           0 :     switch (attr->u.error_code.number / 100) {
     256             :     case 3:
     257             :         /* If the error code is 300 through 399, the client SHOULD consider
     258             :          * the transaction as failed unless the ALTERNATE-SERVER extension is
     259             :          * being used.  See Section 11. */
     260             : 
     261           0 :         if (attr->u.error_code.number == 300) {
     262           0 :             if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_ALTERNATE_SERVER, 0)) {
     263           0 :                 r_log(NR_LOG_STUN, LOG_WARNING, "Missing ALTERNATE-SERVER");
     264           0 :                 ABORT(R_REJECTED);
     265             :             }
     266             : 
     267             :             /* draft-ietf-behave-rfc3489bis-10.txt S 11 */
     268           0 :             if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0)) {
     269           0 :                 r_log(NR_LOG_STUN, LOG_WARNING, "Missing MESSAGE-INTEGRITY");
     270           0 :                 ABORT(R_REJECTED);
     271             :             }
     272             : 
     273           0 :             ABORT(R_RETRY);
     274             :         }
     275             : 
     276           0 :         ABORT(R_REJECTED);
     277             :         break;
     278             : 
     279             :     case 4:
     280             :         /* If the error code is 400 through 499, the client declares the
     281             :          * transaction failed; in the case of 420 (Unknown Attribute), the
     282             :          * response should contain a UNKNOWN-ATTRIBUTES attribute that gives
     283             :          * additional information. */
     284           0 :         if (attr->u.error_code.number == 420)
     285           0 :             ABORT(R_REJECTED);
     286             : 
     287             :         /* it may be possible to restart given the info that was received in
     288             :          * this response, so retry */
     289           0 :         ABORT(R_RETRY);
     290             :         break;
     291             : 
     292             :     case 5:
     293             :         /* If the error code is 500 through 599, the client MAY resend the
     294             :          * request; clients that do so MUST limit the number of times they do
     295             :          * this. */
     296             :         /* let the retransmit mechanism handle resending the request */
     297           0 :         break;
     298             : 
     299             :     default:
     300           0 :         ABORT(R_REJECTED);
     301             :         break;
     302             :     }
     303             : 
     304             :     /* the spec says: "The client then does any processing specified by the authentication
     305             :      * mechanism (see Section 10).  This may result in a new transaction
     306             :      * attempt." -- but this is handled already elsewhere, so needn't be repeated
     307             :      * in this function */
     308             : 
     309           0 :     _status=0;
     310             :  abort:
     311           0 :     return _status;
     312             : }
     313             : 
     314             : /* draft-ietf-behave-rfc3489bis-10.txt S 10.1.2 */
     315             : int
     316           0 : nr_stun_receive_request_or_indication_short_term_auth(nr_stun_message *msg,
     317             :                                                       nr_stun_message *res)
     318             : {
     319             :     int _status;
     320             :     nr_stun_message_attribute *attr;
     321             : 
     322           0 :     switch (msg->header.magic_cookie) {
     323             :     default:
     324             :         /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
     325             :         /* drop thru */
     326             :     case NR_STUN_MAGIC_COOKIE:
     327           0 :         if (!nr_stun_message_has_attribute(msg, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) {
     328           0 :             nr_stun_form_error_response(msg, res, 400, "Missing MESSAGE-INTEGRITY");
     329           0 :             ABORT(R_ALREADY);
     330             :         }
     331             : 
     332           0 :         if (!nr_stun_message_has_attribute(msg, NR_STUN_ATTR_USERNAME, 0)) {
     333           0 :             nr_stun_form_error_response(msg, res, 400, "Missing USERNAME");
     334           0 :             ABORT(R_ALREADY);
     335             :         }
     336             : 
     337           0 :         if (attr->u.message_integrity.unknown_user) {
     338           0 :             nr_stun_form_error_response(msg, res, 401, "Unrecognized USERNAME");
     339           0 :             ABORT(R_ALREADY);
     340             :         }
     341             : 
     342           0 :         if (!attr->u.message_integrity.valid) {
     343           0 :             nr_stun_form_error_response(msg, res, 401, "Bad MESSAGE-INTEGRITY");
     344           0 :             ABORT(R_ALREADY);
     345             :         }
     346             : 
     347           0 :         break;
     348             : 
     349             : #ifdef USE_STUND_0_96
     350             :     case NR_STUN_MAGIC_COOKIE2:
     351             :         /* nothing to check in this case */
     352           0 :         break;
     353             : #endif /* USE_STUND_0_96 */
     354             :     }
     355             : 
     356           0 :     _status=0;
     357             :  abort:
     358           0 :     return _status;
     359             : }
     360             : 
     361             : /* draft-ietf-behave-rfc3489bis-10.txt S 10.1.3 */
     362             : int
     363           0 : nr_stun_receive_response_short_term_auth(nr_stun_message *res)
     364             : {
     365             :     int _status;
     366             :     nr_stun_message_attribute *attr;
     367             : 
     368           0 :     switch (res->header.magic_cookie) {
     369             :     default:
     370             :         /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
     371             :         /* drop thru */
     372             :     case NR_STUN_MAGIC_COOKIE:
     373           0 :         if (!nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) {
     374           0 :             r_log(NR_LOG_STUN, LOG_WARNING, "Missing MESSAGE-INTEGRITY");
     375           0 :             ABORT(R_REJECTED);
     376             :         }
     377             : 
     378           0 :         if (!attr->u.message_integrity.valid) {
     379           0 :             r_log(NR_LOG_STUN, LOG_WARNING, "Bad MESSAGE-INTEGRITY");
     380           0 :             ABORT(R_REJECTED);
     381             :         }
     382             : 
     383           0 :         break;
     384             : 
     385             : #ifdef USE_STUND_0_96
     386             :     case NR_STUN_MAGIC_COOKIE2:
     387             :         /* nothing to check in this case */
     388           0 :         break;
     389             : #endif /* USE_STUND_0_96 */
     390             :     }
     391             : 
     392           0 :    _status=0;
     393             :  abort:
     394           0 :      return _status;
     395             : }
     396             : 
     397             : static int
     398           0 : nr_stun_add_realm_and_nonce(int new_nonce, nr_stun_server_client *clnt, nr_stun_message *res)
     399             : {
     400             :     int r,_status;
     401           0 :     char *realm = 0;
     402             :     char *nonce;
     403             :     UINT2 size;
     404             : 
     405           0 :     if ((r=NR_reg_alloc_string(NR_STUN_REG_PREF_SERVER_REALM, &realm)))
     406           0 :         ABORT(r);
     407             : 
     408           0 :     if ((r=nr_stun_message_add_realm_attribute(res, realm)))
     409           0 :         ABORT(r);
     410             : 
     411           0 :     if (clnt) {
     412           0 :         if (strlen(clnt->nonce) < 1)
     413           0 :             new_nonce = 1;
     414             : 
     415           0 :         if (new_nonce) {
     416           0 :             if (NR_reg_get_uint2(NR_STUN_REG_PREF_SERVER_NONCE_SIZE, &size))
     417           0 :                 size = 48;
     418             : 
     419           0 :             if (size > (sizeof(clnt->nonce) - 1))
     420           0 :                 size = sizeof(clnt->nonce) - 1;
     421             : 
     422           0 :             nr_random_alphanum(clnt->nonce, size);
     423           0 :             clnt->nonce[size] = '\0';
     424             :         }
     425             : 
     426           0 :         nonce = clnt->nonce;
     427             :     }
     428             :     else {
     429             :         /* user is not known, so use a bogus nonce since there's no way to
     430             :          * store a good nonce with the client-specific data -- this nonce
     431             :          * will be recognized as stale if the client attempts another
     432             :          * request */
     433           0 :         nonce = "STALE";
     434             :     }
     435             : 
     436           0 :     if ((r=nr_stun_message_add_nonce_attribute(res, nonce)))
     437           0 :         ABORT(r);
     438             : 
     439           0 :     _status=0;
     440             :  abort:
     441             : #ifdef USE_TURN
     442           0 : assert(_status == 0); /* TODO: !nn! cleanup after I reimplmement TURN */
     443             : #endif
     444           0 :     RFREE(realm);
     445           0 :     return _status;
     446             : }
     447             : 
     448             : /* draft-ietf-behave-rfc3489bis-10.txt S 10.2.1 - 10.2.2 */
     449             : int
     450           0 : nr_stun_receive_request_long_term_auth(nr_stun_message *req, nr_stun_server_ctx *ctx, nr_stun_message *res)
     451             : {
     452             :     int r,_status;
     453             :     nr_stun_message_attribute *mi;
     454             :     nr_stun_message_attribute *n;
     455           0 :     nr_stun_server_client *clnt = 0;
     456             : 
     457           0 :     switch (req->header.magic_cookie) {
     458             :     default:
     459             :         /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
     460             :         /* drop thru */
     461             :     case NR_STUN_MAGIC_COOKIE:
     462           0 :         if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_USERNAME, 0)) {
     463           0 :             nr_stun_form_error_response(req, res, 400, "Missing USERNAME");
     464           0 :             nr_stun_add_realm_and_nonce(0, 0, res);
     465           0 :             ABORT(R_ALREADY);
     466             :         }
     467             : 
     468           0 :         if ((r=nr_stun_get_message_client(ctx, req, &clnt))) {
     469           0 :             nr_stun_form_error_response(req, res, 401, "Unrecognized USERNAME");
     470           0 :             nr_stun_add_realm_and_nonce(0, 0, res);
     471           0 :             ABORT(R_ALREADY);
     472             :         }
     473             : 
     474           0 :         if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_MESSAGE_INTEGRITY, &mi)) {
     475           0 :             nr_stun_form_error_response(req, res, 401, "Missing MESSAGE-INTEGRITY");
     476           0 :             nr_stun_add_realm_and_nonce(0, clnt, res);
     477           0 :             ABORT(R_ALREADY);
     478             :         }
     479             : 
     480           0 :         assert(!mi->u.message_integrity.unknown_user);
     481             : 
     482           0 :         if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_REALM, 0)) {
     483           0 :             nr_stun_form_error_response(req, res, 400, "Missing REALM");
     484           0 :             ABORT(R_ALREADY);
     485             :         }
     486             : 
     487           0 :         if (!nr_stun_message_has_attribute(req, NR_STUN_ATTR_NONCE, &n)) {
     488           0 :             nr_stun_form_error_response(req, res, 400, "Missing NONCE");
     489           0 :             ABORT(R_ALREADY);
     490             :         }
     491             : 
     492             :         assert(sizeof(clnt->nonce) == sizeof(n->u.nonce));
     493           0 :         if (strncmp(clnt->nonce, n->u.nonce, sizeof(n->u.nonce))) {
     494           0 :             nr_stun_form_error_response(req, res, 438, "Stale NONCE");
     495           0 :             nr_stun_add_realm_and_nonce(1, clnt, res);
     496           0 :             ABORT(R_ALREADY);
     497             :         }
     498             : 
     499           0 :         if (!mi->u.message_integrity.valid) {
     500           0 :             nr_stun_form_error_response(req, res, 401, "Bad MESSAGE-INTEGRITY");
     501           0 :             nr_stun_add_realm_and_nonce(0, clnt, res);
     502           0 :             ABORT(R_ALREADY);
     503             :         }
     504             : 
     505           0 :         break;
     506             : 
     507             : #ifdef USE_STUND_0_96
     508             :     case NR_STUN_MAGIC_COOKIE2:
     509             :         /* nothing to do in this case */
     510           0 :         break;
     511             : #endif /* USE_STUND_0_96 */
     512             :     }
     513             : 
     514           0 :     _status=0;
     515             :  abort:
     516             : 
     517           0 :     return _status;
     518             : }
     519             : 
     520             : /* draft-ietf-behave-rfc3489bis-10.txt S 10.2.3 */
     521             : int
     522           0 : nr_stun_receive_response_long_term_auth(nr_stun_message *res, nr_stun_client_ctx *ctx)
     523             : {
     524             :     int _status;
     525             :     nr_stun_message_attribute *attr;
     526             : 
     527           0 :     switch (res->header.magic_cookie) {
     528             :     default:
     529             :         /* in RFC 3489 there is no magic cookie, it's part of the transaction ID */
     530             :         /* drop thru */
     531             :     case NR_STUN_MAGIC_COOKIE:
     532           0 :         if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_REALM, &attr)) {
     533           0 :             RFREE(ctx->realm);
     534           0 :             ctx->realm = r_strdup(attr->u.realm);
     535           0 :             if (!ctx->realm)
     536           0 :                 ABORT(R_NO_MEMORY);
     537             :         }
     538             :         else {
     539           0 :             r_log(NR_LOG_STUN, LOG_WARNING, "Missing REALM");
     540           0 :             ABORT(R_REJECTED);
     541             :         }
     542             : 
     543           0 :         if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_NONCE, &attr)) {
     544           0 :             RFREE(ctx->nonce);
     545           0 :             ctx->nonce = r_strdup(attr->u.nonce);
     546           0 :             if (!ctx->nonce)
     547           0 :                 ABORT(R_NO_MEMORY);
     548             :         }
     549             :         else {
     550           0 :             r_log(NR_LOG_STUN, LOG_WARNING, "Missing NONCE");
     551           0 :             ABORT(R_REJECTED);
     552             :         }
     553             : 
     554           0 :         if (nr_stun_message_has_attribute(res, NR_STUN_ATTR_MESSAGE_INTEGRITY, &attr)) {
     555           0 :             if (!attr->u.message_integrity.valid) {
     556           0 :                 r_log(NR_LOG_STUN, LOG_WARNING, "Bad MESSAGE-INTEGRITY");
     557           0 :                 ABORT(R_REJECTED);
     558             :             }
     559             :         }
     560             : 
     561           0 :         break;
     562             : 
     563             : #ifdef USE_STUND_0_96
     564             :     case NR_STUN_MAGIC_COOKIE2:
     565             :         /* nothing to check in this case */
     566           0 :         break;
     567             : #endif /* USE_STUND_0_96 */
     568             :     }
     569             : 
     570           0 :     _status=0;
     571             :  abort:
     572           0 :     return _status;
     573             : }
     574             : 

Generated by: LCOV version 1.13