encode_digest.c

Go to the documentation of this file.
00001 /* $Id: encode_digest.c 5192 2008-11-13 10:18:48Z eliasbaixas $
00002  *
00003  * Copyright (C) 2006-2007 VozTelecom Sistemas S.L
00004  *
00005  * This file is part of Kamailio, a free SIP server.
00006  *
00007  * Kamailio is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version
00011  *
00012  * Kamailio is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License 
00018  * along with this program; if not, write to the Free Software 
00019  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020  */
00021 
00022 /*
00023  * =====================================================================================
00024  * 
00025  *        Filename:  encode_digest.c
00026  * 
00027  *     Description:  functions to encode/decode/print Digest headers ([proxy,www]-[authenticate,require])
00028  * 
00029  *         Version:  1.0
00030  *         Created:  20/11/05 04:24:55 CET
00031  *        Revision:  none
00032  *        Compiler:  gcc
00033  * 
00034  *          Author:  Elias Baixas (EB), elias@conillera.net
00035  *         Company:  VozTele.com
00036  * 
00037  * =====================================================================================
00038  */
00039 #define _GNU_SOURCE
00040 #include <stdio.h>
00041 
00042 #include "../../parser/digest/digest_parser.h"
00043 #include "../../parser/parse_uri.h"
00044 #include "../../parser/digest/digest.h"
00045 #include "encode_digest.h"
00046 #include "xaddress.h"
00047 #include "encode_header.h"
00048 #include "encode_uri.h"
00049 
00050 #define HAS_NAME_F      0x01
00051 #define HAS_REALM_F     0x02
00052 #define HAS_NONCE_F     0x04
00053 #define HAS_URI_F    0x08
00054 #define HAS_RESPONSE_F     0x10
00055 #define HAS_ALG_F    0x20
00056 #define HAS_CNONCE_F    0x40
00057 #define HAS_OPAQUE_F    0x80
00058 #define HAS_QoP_F    0x01
00059 #define HAS_NC_F     0x02
00060 /*
00061  * encodes a digest header body.
00062  * encoding is:
00063  * 1: flags
00064  * HAS_NAME_F     0x01
00065  * HAS_REALM_F    0x02
00066  * HAS_NONCE_F    0x04
00067  * HAS_URI_F      0x08
00068  * HAS_RESPONSE_F 0x10
00069  * HAS_ALG_F      0x20
00070  * HAS_CNONCE_F      0x40
00071  * HAS_OPAQUE_F      0x80
00072  * 1: flags
00073  * HAS_QoP_F      0x01
00074  * HAS_NC_F    0x02
00075  * 2: hdr-start based pointer to where the scheme starts + length of the scheme (must be Digest).
00076  * 
00077  * for each field present, there are 2 bytes, one pointing the place where it starts, 
00078  * the next signaling how long this field is. The URI is a special case, and is composed of 1
00079  * byte telling how long is the URI structure, and then the encoded URI structure.
00080  */
00081 
00082 int encode_digest(char *hdrstart,int hdrlen,dig_cred_t *digest,unsigned char *where)
00083 {
00084    int i=2,j=0;/* 2*flags */
00085    unsigned char flags1=0,flags2=0;
00086    struct sip_uri sipuri;
00087 
00088    if(digest->username.whole.s && digest->username.whole.len){
00089       flags1|=HAS_NAME_F;
00090       where[i++]=(unsigned char)(digest->username.whole.s-hdrstart);
00091       where[i++]=(unsigned char)digest->username.whole.len;
00092    }
00093    if(digest->realm.s && digest->realm.len){
00094       flags1|=HAS_REALM_F;
00095       where[i++]=(unsigned char)(digest->realm.s-hdrstart);
00096       where[i++]=(unsigned char)digest->realm.len;
00097    }
00098    if(digest->nonce.s && digest->nonce.len){
00099       flags1|=HAS_NONCE_F;
00100       where[i++]=(unsigned char)(digest->nonce.s-hdrstart);
00101       where[i++]=(unsigned char)digest->nonce.len;
00102    }
00103    if(digest->uri.s && digest->uri.len){
00104       memset(&sipuri,0,sizeof(struct sip_uri));
00105       flags1|=HAS_URI_F;
00106       if (parse_uri(digest->uri.s, digest->uri.len,&sipuri) < 0 ) {
00107     LM_ERR("Bad URI in address\n");
00108     return -1;
00109       }else{
00110     if((j=encode_uri2(hdrstart,hdrlen,digest->uri,&sipuri,&where[i+1]))<0){
00111        LM_ERR("Error encoding the URI\n");
00112        return -1;
00113     }else{
00114        where[i]=(unsigned char)j;
00115        i+=(j+1);
00116     }
00117       }
00118    }
00119    if(digest->response.s && digest->response.len){
00120       flags1|=HAS_RESPONSE_F;
00121       where[i++]=(unsigned char)(digest->response.s-hdrstart);
00122       where[i++]=(unsigned char)digest->response.len;
00123    }
00124    if(digest->alg.alg_str.s && digest->alg.alg_str.len){
00125       flags1|=HAS_ALG_F;
00126       where[i++]=(unsigned char)(digest->alg.alg_str.s-hdrstart);
00127       where[i++]=(unsigned char)digest->alg.alg_str.len;
00128    }
00129    if(digest->cnonce.s && digest->cnonce.len){
00130       flags1|=HAS_CNONCE_F;
00131       where[i++]=(unsigned char)(digest->cnonce.s-hdrstart);
00132       where[i++]=(unsigned char)digest->cnonce.len;
00133    }
00134    if(digest->opaque.s && digest->opaque.len){
00135       flags1|=HAS_OPAQUE_F;
00136       where[i++]=(unsigned char)(digest->opaque.s-hdrstart);
00137       where[i++]=(unsigned char)digest->opaque.len;
00138    }
00139    if(digest->qop.qop_str.s && digest->qop.qop_str.len){
00140       flags2|=HAS_QoP_F;
00141       where[i++]=(unsigned char)(digest->qop.qop_str.s-hdrstart);
00142       where[i++]=(unsigned char)digest->qop.qop_str.len;
00143    }
00144    if(digest->nc.s && digest->nc.len){
00145       flags2|=HAS_NC_F;
00146       where[i++]=(unsigned char)(digest->nc.s-hdrstart);
00147       where[i++]=(unsigned char)digest->nc.len;
00148    }
00149    where[0]=flags1;
00150    where[1]=flags2;
00151    return i;
00152 }
00153 
00154 
00155 int print_encoded_digest(FILE *fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix)
00156 {
00157    int i=2;/* flags + flags1 */
00158    unsigned char flags1,flags2;
00159 
00160    flags1=payload[0];
00161    flags2=payload[1];
00162    fprintf(fd,"%s",prefix);
00163    for(i=0;i<paylen;i++)
00164       fprintf(fd,"%s%d%s",i==0?"ENCODED DIGEST=[":":",payload[i],i==paylen-1?"]\n":"");
00165    i=2;
00166    if(flags1 & HAS_NAME_F){
00167       fprintf(fd,"%sDIGEST NAME=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00168       i+=2;
00169    }
00170    if(flags1& HAS_REALM_F){
00171       fprintf(fd,"%sDIGEST REALM=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00172       i+=2;
00173    }
00174    if(flags1& HAS_NONCE_F){
00175       fprintf(fd,"%sDIGEST NONCE=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00176       i+=2;
00177    }
00178    if(flags1& HAS_URI_F){
00179       if(print_encoded_uri(fd,&payload[i+1],payload[i],hdr,hdrlen,strcat(prefix,"  "))<0){
00180     prefix[strlen(prefix)-2]=0;
00181     fprintf(fd,"Error parsing encoded URI\n");
00182     return -1;
00183       }
00184       i+=payload[i]+1;
00185    }
00186    if(flags1& HAS_RESPONSE_F){
00187       fprintf(fd,"%sDIGEST RESPONSE=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00188       i+=2;
00189    }
00190    if(flags1& HAS_ALG_F){
00191       fprintf(fd,"%sDIGEST ALGORITHM=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00192       i+=2;
00193    }
00194    if(flags1& HAS_CNONCE_F){
00195       fprintf(fd,"%sDIGEST CNONCE=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00196       i+=2;
00197    }
00198    if(flags1& HAS_OPAQUE_F){
00199       fprintf(fd,"%sDIGEST OPAQUE=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00200       i+=2;
00201    }
00202    if(flags2& HAS_QoP_F){
00203       fprintf(fd,"%sDIGEST QualityOfProtection=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00204       i+=2;
00205    }
00206    if(flags2& HAS_NC_F){
00207       fprintf(fd,"%sDIGEST NonceCount=[%.*s]\n",prefix,payload[i+1],&hdr[payload[i]]);
00208       i+=2;
00209    }
00210    return 0;
00211 }
00212 
00213 
00214 /**
00215  *
00216  */
00217 int dump_digest_test(char *hdr,int hdrlen,unsigned char* payload,int paylen,FILE* fd,char segregationLevel)
00218 {
00219    int i=2;/* 2*flags */
00220    unsigned char flags1=0,flags2=0;
00221 
00222    flags1=payload[0];
00223    flags2=payload[1];
00224    if(!(segregationLevel & ONLY_URIS))
00225       return dump_standard_hdr_test(hdr,hdrlen,payload,paylen,fd);
00226    i=2;
00227    if(flags1 & HAS_NAME_F)
00228       i+=2;
00229    if(flags1 & HAS_REALM_F)
00230       i+=2;
00231    if(flags1 & HAS_NONCE_F)
00232       i+=2;
00233    if(flags1 & HAS_URI_F){
00234       if(!(segregationLevel & JUNIT) && (segregationLevel & ONLY_URIS))
00235     return dump_standard_hdr_test(hdr,hdrlen,&payload[i+1],payload[i],fd);
00236       if((segregationLevel & JUNIT) && (segregationLevel & ONLY_URIS))
00237     return print_uri_junit_tests(hdr,hdrlen,&payload[i+1],payload[i],fd,1,"");
00238    }
00239    return 0;
00240 }

Generated on Wed May 23 06:00:45 2012 for Kamailio - The Open Source SIP Server by  doxygen 1.5.6