LCOV - code coverage report
Current view: top level - media/mtransport/third_party/nICEr/src/stun - stun_server_ctx.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 196 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 12 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             : 
      35             : static char *RCSSTRING __UNUSED__="$Id: stun_server_ctx.c,v 1.2 2008/04/28 18:21:30 ekr Exp $";
      36             : 
      37             : #include <string.h>
      38             : #include <assert.h>
      39             : 
      40             : #include "nr_api.h"
      41             : #include "stun.h"
      42             : 
      43             : static int nr_stun_server_destroy_client(nr_stun_server_client *clnt);
      44             : static int nr_stun_server_send_response(nr_stun_server_ctx *ctx, nr_socket *sock, nr_transport_addr *peer_addr, nr_stun_message *res, nr_stun_server_client *clnt);
      45             : static int nr_stun_server_process_request_auth_checks(nr_stun_server_ctx *ctx, nr_stun_message *req, int auth_rule, nr_stun_message *res);
      46             : 
      47             : 
      48           0 : int nr_stun_server_ctx_create(char *label, nr_socket *sock, nr_stun_server_ctx **ctxp)
      49             :   {
      50             :     int r,_status;
      51           0 :     nr_stun_server_ctx *ctx=0;
      52             : 
      53           0 :     if ((r=nr_stun_startup()))
      54           0 :       ABORT(r);
      55             : 
      56           0 :     if(!(ctx=RCALLOC(sizeof(nr_stun_server_ctx))))
      57           0 :       ABORT(R_NO_MEMORY);
      58             : 
      59           0 :     if(!(ctx->label=r_strdup(label)))
      60           0 :       ABORT(R_NO_MEMORY);
      61           0 :     ctx->sock=sock;
      62           0 :     nr_socket_getaddr(sock,&ctx->my_addr);
      63             : 
      64           0 :     STAILQ_INIT(&ctx->clients);
      65             : 
      66           0 :     *ctxp=ctx;
      67             : 
      68           0 :     _status=0;
      69             :   abort:
      70           0 :     return(_status);
      71             :   }
      72             : 
      73           0 : int nr_stun_server_ctx_destroy(nr_stun_server_ctx **ctxp)
      74             :   {
      75             :     nr_stun_server_ctx *ctx;
      76             :     nr_stun_server_client *clnt1,*clnt2;
      77             : 
      78           0 :     if(!ctxp || !*ctxp)
      79           0 :       return(0);
      80             : 
      81           0 :     ctx=*ctxp;
      82             : 
      83           0 :     STAILQ_FOREACH_SAFE(clnt1, &ctx->clients, entry, clnt2) {
      84           0 :         nr_stun_server_destroy_client(clnt1);
      85             :     }
      86             : 
      87           0 :     nr_stun_server_destroy_client(ctx->default_client);
      88             : 
      89           0 :     RFREE(ctx->label);
      90           0 :     RFREE(ctx);
      91             : 
      92           0 :     return(0);
      93             :   }
      94             : 
      95           0 : static int nr_stun_server_client_create(nr_stun_server_ctx *ctx, char *client_label, char *user, Data *pass, nr_stun_server_cb cb, void *cb_arg, nr_stun_server_client **clntp)
      96             :   {
      97           0 :     nr_stun_server_client *clnt=0;
      98             :     int r,_status;
      99             : 
     100           0 :     if(!(clnt=RCALLOC(sizeof(nr_stun_server_client))))
     101           0 :       ABORT(R_NO_MEMORY);
     102             : 
     103           0 :     if(!(clnt->label=r_strdup(client_label)))
     104           0 :       ABORT(R_NO_MEMORY);
     105             : 
     106           0 :     if(!(clnt->username=r_strdup(user)))
     107           0 :       ABORT(R_NO_MEMORY);
     108             : 
     109           0 :     if(r=r_data_copy(&clnt->password,pass))
     110           0 :       ABORT(r);
     111             : 
     112           0 :     r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(%s)/CLIENT(%s): Adding client for %s",ctx->label, client_label, user);
     113           0 :     clnt->stun_server_cb=cb;
     114           0 :     clnt->cb_arg=cb_arg;
     115             : 
     116           0 :     *clntp = clnt;
     117           0 :     _status=0;
     118             :  abort:
     119           0 :     if(_status){
     120           0 :       nr_stun_server_destroy_client(clnt);
     121             :     }
     122           0 :     return(_status);
     123             :   }
     124             : 
     125           0 : int nr_stun_server_add_client(nr_stun_server_ctx *ctx, char *client_label, char *user, Data *pass, nr_stun_server_cb cb, void *cb_arg)
     126             :   {
     127             :    int r,_status;
     128             :    nr_stun_server_client *clnt;
     129             : 
     130           0 :     if (r=nr_stun_server_client_create(ctx, client_label, user, pass, cb, cb_arg, &clnt))
     131           0 :       ABORT(r);
     132             : 
     133           0 :     STAILQ_INSERT_TAIL(&ctx->clients,clnt,entry);
     134             : 
     135           0 :     _status=0;
     136             :   abort:
     137           0 :     return(_status);
     138             :   }
     139             : 
     140           0 : int nr_stun_server_add_default_client(nr_stun_server_ctx *ctx, char *ufrag, Data *pass, nr_stun_server_cb cb, void *cb_arg)
     141             :   {
     142             :     int r,_status;
     143             :     nr_stun_server_client *clnt;
     144             : 
     145           0 :     assert(!ctx->default_client);
     146           0 :     if (ctx->default_client)
     147           0 :       ABORT(R_INTERNAL);
     148             : 
     149           0 :     if (r=nr_stun_server_client_create(ctx, "default_client", ufrag, pass, cb, cb_arg, &clnt))
     150           0 :       ABORT(r);
     151             : 
     152           0 :     ctx->default_client = clnt;
     153             : 
     154           0 :     _status=0;
     155             :   abort:
     156           0 :     return(_status);
     157             :   }
     158             : 
     159           0 : int nr_stun_server_remove_client(nr_stun_server_ctx *ctx, void *cb_arg)
     160             :   {
     161             :     nr_stun_server_client *clnt1,*clnt2;
     162           0 :     int found = 0;
     163             : 
     164           0 :     STAILQ_FOREACH_SAFE(clnt1, &ctx->clients, entry, clnt2) {
     165           0 :       if(clnt1->cb_arg == cb_arg) {
     166           0 :         STAILQ_REMOVE(&ctx->clients, clnt1, nr_stun_server_client_, entry);
     167           0 :         nr_stun_server_destroy_client(clnt1);
     168           0 :         found++;
     169             :       }
     170             :     }
     171             : 
     172           0 :     if (!found)
     173           0 :       ERETURN(R_NOT_FOUND);
     174             : 
     175           0 :     return 0;
     176             :   }
     177             : 
     178           0 : static int nr_stun_server_get_password(void *arg, nr_stun_message *msg, Data **password)
     179             :   {
     180             :     int _status;
     181           0 :     nr_stun_server_ctx *ctx = (nr_stun_server_ctx*)arg;
     182           0 :     nr_stun_server_client *clnt = 0;
     183             :     nr_stun_message_attribute *username_attribute;
     184             : 
     185           0 :     if ((nr_stun_get_message_client(ctx, msg, &clnt))) {
     186           0 :         if (! nr_stun_message_has_attribute(msg, NR_STUN_ATTR_USERNAME, &username_attribute)) {
     187           0 :            r_log(NR_LOG_STUN,LOG_WARNING,"STUN-SERVER(%s): Missing Username",ctx->label);
     188           0 :            ABORT(R_NOT_FOUND);
     189             :         }
     190             : 
     191             :         /* Although this is an exceptional condition, we'll already have seen a
     192             :          * NOTICE-level log message about the unknown user, so additional log
     193             :          * messages at any level higher than DEBUG are unnecessary. */
     194             : 
     195           0 :         r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(%s): Unable to find password for unknown user: %s",ctx->label,username_attribute->u.username);
     196           0 :         ABORT(R_NOT_FOUND);
     197             :     }
     198             : 
     199           0 :     *password = &clnt->password;
     200             : 
     201           0 :     _status=0;
     202             :   abort:
     203           0 :     return(_status);
     204             :   }
     205             : 
     206           0 : int nr_stun_server_process_request_auth_checks(nr_stun_server_ctx *ctx, nr_stun_message *req, int auth_rule, nr_stun_message *res)
     207             :   {
     208             :     int r,_status;
     209             : 
     210           0 :     if (nr_stun_message_has_attribute(req, NR_STUN_ATTR_MESSAGE_INTEGRITY, 0)
     211           0 :      || !(auth_rule & NR_STUN_AUTH_RULE_OPTIONAL)) {
     212             :         /* favor long term credentials over short term, if both are supported */
     213             : 
     214           0 :         if (auth_rule & NR_STUN_AUTH_RULE_LONG_TERM) {
     215           0 :             if ((r=nr_stun_receive_request_long_term_auth(req, ctx, res)))
     216           0 :                 ABORT(r);
     217             :         }
     218           0 :         else if (auth_rule & NR_STUN_AUTH_RULE_SHORT_TERM) {
     219           0 :             if ((r=nr_stun_receive_request_or_indication_short_term_auth(req, res)))
     220           0 :                 ABORT(r);
     221             :         }
     222             :     }
     223             : 
     224           0 :     _status=0;
     225             :   abort:
     226           0 :     return(_status);
     227             :   }
     228             : 
     229           0 : int nr_stun_server_process_request(nr_stun_server_ctx *ctx, nr_socket *sock, char *msg, int len, nr_transport_addr *peer_addr, int auth_rule)
     230             :   {
     231             :     int r,_status;
     232             :     char string[256];
     233           0 :     nr_stun_message *req = 0;
     234           0 :     nr_stun_message *res = 0;
     235           0 :     nr_stun_server_client *clnt = 0;
     236             :     nr_stun_server_request info;
     237             :     int error;
     238           0 :     int dont_free = 0;
     239             : 
     240           0 :     r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(%s): Received(my_addr=%s,peer_addr=%s)",ctx->label,ctx->my_addr.as_string,peer_addr->as_string);
     241             : 
     242           0 :     snprintf(string, sizeof(string)-1, "STUN-SERVER(%s): Received ", ctx->label);
     243           0 :     r_dump(NR_LOG_STUN, LOG_DEBUG, string, (char*)msg, len);
     244             : 
     245           0 :     memset(&info,0,sizeof(info));
     246             : 
     247           0 :     if ((r=nr_stun_message_create2(&req, (UCHAR*)msg, len)))
     248           0 :         ABORT(r);
     249             : 
     250           0 :     if ((r=nr_stun_message_create(&res)))
     251           0 :         ABORT(r);
     252             : 
     253           0 :     if ((r=nr_stun_decode_message(req, nr_stun_server_get_password, ctx))) {
     254             :         /* RFC5389 S 7.3 says "If any errors are detected, the message is
     255             :          * silently discarded."  */
     256             : #ifndef USE_STUN_PEDANTIC
     257             :         /* ... but that seems like a bad idea, at least return a 400 so
     258             :          * that the server isn't a black hole to the client */
     259             :         nr_stun_form_error_response(req, res, 400, "Bad Request - Failed to decode request");
     260             :         ABORT(R_ALREADY);
     261             : #endif /* USE_STUN_PEDANTIC */
     262           0 :         ABORT(R_REJECTED);
     263             :     }
     264             : 
     265           0 :     if ((r=nr_stun_receive_message(0, req))) {
     266             :         /* RFC5389 S 7.3 says "If any errors are detected, the message is
     267             :          * silently discarded."  */
     268             : #ifndef USE_STUN_PEDANTIC
     269             :         /* ... but that seems like a bad idea, at least return a 400 so
     270             :          * that the server isn't a black hole to the client */
     271             :         nr_stun_form_error_response(req, res, 400, "Bad Request - Section 7.3 check failed");
     272             :         ABORT(R_ALREADY);
     273             : #endif /* USE_STUN_PEDANTIC */
     274           0 :         ABORT(R_REJECTED);
     275             :     }
     276             : 
     277           0 :     if (NR_STUN_GET_TYPE_CLASS(req->header.type) != NR_CLASS_REQUEST
     278           0 :      && NR_STUN_GET_TYPE_CLASS(req->header.type) != NR_CLASS_INDICATION) {
     279           0 :          r_log(NR_LOG_STUN,LOG_WARNING,"STUN-SERVER(%s): Illegal message type: %04x",ctx->label,req->header.type);
     280             :         /* RFC5389 S 7.3 says "If any errors are detected, the message is
     281             :          * silently discarded."  */
     282             : #ifndef USE_STUN_PEDANTIC
     283             :         /* ... but that seems like a bad idea, at least return a 400 so
     284             :          * that the server isn't a black hole to the client */
     285             :         nr_stun_form_error_response(req, res, 400, "Bad Request - Unsupported message type");
     286             :         ABORT(R_ALREADY);
     287             : #endif /* USE_STUN_PEDANTIC */
     288           0 :         ABORT(R_REJECTED);
     289             :     }
     290             : 
     291             :     /* "The STUN agent then does any checks that are required by a
     292             :      * authentication mechanism that the usage has specified" */
     293           0 :     if ((r=nr_stun_server_process_request_auth_checks(ctx, req, auth_rule, res)))
     294           0 :         ABORT(r);
     295             : 
     296           0 :     if (NR_STUN_GET_TYPE_CLASS(req->header.type) == NR_CLASS_INDICATION) {
     297           0 :         if ((r=nr_stun_process_indication(req)))
     298           0 :             ABORT(r);
     299             :     }
     300             :     else {
     301           0 :         if ((r=nr_stun_process_request(req, res)))
     302           0 :             ABORT(r);
     303             :     }
     304             : 
     305           0 :     assert(res->header.type == 0);
     306             : 
     307           0 :     clnt = 0;
     308           0 :     if (NR_STUN_GET_TYPE_CLASS(req->header.type) == NR_CLASS_REQUEST) {
     309           0 :         if ((nr_stun_get_message_client(ctx, req, &clnt))) {
     310           0 :             if ((r=nr_stun_form_success_response(req, peer_addr, 0, res)))
     311           0 :                 ABORT(r);
     312             :         }
     313             :         else {
     314           0 :             if ((r=nr_stun_form_success_response(req, peer_addr, &clnt->password, res)))
     315           0 :                 ABORT(r);
     316             :         }
     317             :     }
     318             : 
     319           0 :     if(clnt && clnt->stun_server_cb){
     320           0 :         r_log(NR_LOG_STUN,LOG_DEBUG,"Entering STUN server callback");
     321             : 
     322             :         /* Set up the info */
     323           0 :         if(r=nr_transport_addr_copy(&info.src_addr,peer_addr))
     324           0 :             ABORT(r);
     325             : 
     326           0 :         info.request = req;
     327           0 :         info.response = res;
     328             : 
     329           0 :         error = 0;
     330           0 :         dont_free = 0;
     331           0 :         if (clnt->stun_server_cb(clnt->cb_arg,ctx,sock,&info,&dont_free,&error)) {
     332           0 :             if (error == 0)
     333           0 :                 error = 500;
     334             : 
     335           0 :             nr_stun_form_error_response(req, res, error, "ICE Failure");
     336           0 :             ABORT(R_ALREADY);
     337             :         }
     338             :     }
     339             : 
     340           0 :     _status=0;
     341             :   abort:
     342           0 :     if (!res)
     343           0 :         goto skip_response;
     344             : 
     345           0 :     if (NR_STUN_GET_TYPE_CLASS(req->header.type) == NR_CLASS_INDICATION)
     346           0 :         goto skip_response;
     347             : 
     348             :     /* Now respond */
     349             : 
     350           0 :     if (_status != 0 && ! nr_stun_message_has_attribute(res, NR_STUN_ATTR_ERROR_CODE, 0))
     351           0 :          nr_stun_form_error_response(req, res, 500, "Failed to specify error");
     352             : 
     353           0 :     if ((r=nr_stun_server_send_response(ctx, sock, peer_addr, res, clnt))) {
     354           0 :         r_log(NR_LOG_STUN,LOG_ERR,"STUN-SERVER(label=%s): Failed sending response (my_addr=%s,peer_addr=%s)",ctx->label,ctx->my_addr.as_string,peer_addr->as_string);
     355           0 :         _status = R_FAILED;
     356             :     }
     357             : 
     358             : #if 0
     359             :     /* EKR: suppressed these checks because if you have an error when
     360             :        you are sending an error, things go wonky */
     361             : #ifdef SANITY_CHECKS
     362             :     if (_status == R_ALREADY) {
     363             :         assert(NR_STUN_GET_TYPE_CLASS(res->header.type) == NR_CLASS_ERROR_RESPONSE);
     364             :         assert(nr_stun_message_has_attribute(res, NR_STUN_ATTR_ERROR_CODE, 0));
     365             :     }
     366             :     else {
     367             :         assert(NR_STUN_GET_TYPE_CLASS(res->header.type) == NR_CLASS_RESPONSE);
     368             :         assert(!nr_stun_message_has_attribute(res, NR_STUN_ATTR_ERROR_CODE, 0));
     369             :     }
     370             : #endif /* SANITY_CHECKS */
     371             : #endif
     372             : 
     373             :     if (0) {
     374             :   skip_response:
     375           0 :         _status = 0;
     376             :     }
     377             : 
     378           0 :     if (!dont_free) {
     379           0 :       nr_stun_message_destroy(&res);
     380           0 :       nr_stun_message_destroy(&req);
     381             :     }
     382             : 
     383           0 :     return(_status);
     384             :   }
     385             : 
     386           0 : static int nr_stun_server_send_response(nr_stun_server_ctx *ctx, nr_socket *sock, nr_transport_addr *peer_addr, nr_stun_message *res, nr_stun_server_client *clnt)
     387             :   {
     388             :     int r,_status;
     389             :     Data *hmacPassword;
     390             :     char string[256];
     391             : 
     392           0 :     r_log(NR_LOG_STUN,LOG_DEBUG,"STUN-SERVER(label=%s): Sending(my_addr=%s,peer_addr=%s)",ctx->label,ctx->my_addr.as_string,peer_addr->as_string);
     393             : 
     394           0 :     if (clnt) {
     395           0 :         hmacPassword = &clnt->password;
     396             :     }
     397             :     else {
     398           0 :         hmacPassword = 0;
     399             :     }
     400             : 
     401           0 :     if ((r=nr_stun_encode_message(res))) {
     402             :         /* should never happen */
     403           0 :         r_log(NR_LOG_STUN,LOG_ERR,"STUN-SERVER(label=%s): Unable to encode message", ctx->label);
     404             :     }
     405             :     else {
     406           0 :         snprintf(string, sizeof(string)-1, "STUN(%s): Sending to %s ", ctx->label, peer_addr->as_string);
     407           0 :         r_dump(NR_LOG_STUN, LOG_DEBUG, string, (char*)res->buffer, res->length);
     408             : 
     409           0 :         if(r=nr_socket_sendto(sock?sock:ctx->sock,res->buffer,res->length,0,peer_addr))
     410           0 :           ABORT(r);
     411             :     }
     412             : 
     413           0 :     _status=0;
     414             :   abort:
     415           0 :     return(_status);
     416             :   }
     417             : 
     418           0 : static int nr_stun_server_destroy_client(nr_stun_server_client *clnt)
     419             :   {
     420           0 :     if (!clnt)
     421           0 :       return 0;
     422             : 
     423           0 :     RFREE(clnt->label);
     424           0 :     RFREE(clnt->username);
     425           0 :     r_data_zfree(&clnt->password);
     426             : 
     427           0 :     RFREE(clnt);
     428           0 :     return(0);
     429             :   }
     430             : 
     431           0 : int nr_stun_get_message_client(nr_stun_server_ctx *ctx, nr_stun_message *req, nr_stun_server_client **out)
     432             :   {
     433             :     int _status;
     434             :     nr_stun_message_attribute *attr;
     435           0 :     nr_stun_server_client *clnt=0;
     436             : 
     437           0 :     if (! nr_stun_message_has_attribute(req, NR_STUN_ATTR_USERNAME, &attr)) {
     438           0 :        r_log(NR_LOG_STUN,LOG_WARNING,"STUN-SERVER(%s): Missing Username",ctx->label);
     439           0 :        ABORT(R_NOT_FOUND);
     440             :     }
     441             : 
     442           0 :     STAILQ_FOREACH(clnt, &ctx->clients, entry) {
     443           0 :         if (!strncmp(clnt->username, attr->u.username,
     444             :                      sizeof(attr->u.username)))
     445           0 :             break;
     446             :     }
     447             : 
     448           0 :     if (!clnt && ctx->default_client) {
     449             :       /* If we can't find a specific client see if this matches the default,
     450             :          which means that the username starts with our ufrag.
     451             :        */
     452           0 :       char *colon = strchr(attr->u.username, ':');
     453           0 :       if (colon && !strncmp(ctx->default_client->username,
     454           0 :                             attr->u.username,
     455           0 :                             colon - attr->u.username)) {
     456           0 :         clnt = ctx->default_client;
     457           0 :         r_log(NR_LOG_STUN,LOG_NOTICE,"STUN-SERVER(%s): Falling back to default client, username=: %s",ctx->label,attr->u.username);
     458             :       }
     459             :     }
     460             : 
     461           0 :     if (!clnt) {
     462           0 :         r_log(NR_LOG_STUN,LOG_WARNING,"STUN-SERVER(%s): Request from unknown user: %s",ctx->label,attr->u.username);
     463           0 :         ABORT(R_NOT_FOUND);
     464             :     }
     465             : 
     466           0 :     *out = clnt;
     467             : 
     468           0 :     _status=0;
     469             :   abort:
     470           0 :     return(_status);
     471             :   }
     472             : 

Generated by: LCOV version 1.13