/* $Id$ * * Copyright (C) 2006-2007 VozTelecom Sistemas S.L * * This file is part of Kamailio, a free SIP server. * * Kamailio 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 * * Kamailio 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 */ /* * ===================================================================================== * * Filename: encode_digest.c * * Description: functions to encode/decode/print Digest headers ([proxy,www]-[authenticate,require]) * * Version: 1.0 * Created: 20/11/05 04:24:55 CET * Revision: none * Compiler: gcc * * Author: Elias Baixas (EB), elias@conillera.net * Company: VozTele.com * * ===================================================================================== */ #define _GNU_SOURCE #include #include "../../parser/digest/digest_parser.h" #include "../../parser/parse_uri.h" #include "../../parser/digest/digest.h" #include "encode_digest.h" #include "xaddress.h" #include "encode_header.h" #include "encode_uri.h" #define HAS_NAME_F 0x01 #define HAS_REALM_F 0x02 #define HAS_NONCE_F 0x04 #define HAS_URI_F 0x08 #define HAS_RESPONSE_F 0x10 #define HAS_ALG_F 0x20 #define HAS_CNONCE_F 0x40 #define HAS_OPAQUE_F 0x80 #define HAS_QoP_F 0x01 #define HAS_NC_F 0x02 /* * encodes a digest header body. * encoding is: * 1: flags * HAS_NAME_F 0x01 * HAS_REALM_F 0x02 * HAS_NONCE_F 0x04 * HAS_URI_F 0x08 * HAS_RESPONSE_F 0x10 * HAS_ALG_F 0x20 * HAS_CNONCE_F 0x40 * HAS_OPAQUE_F 0x80 * 1: flags * HAS_QoP_F 0x01 * HAS_NC_F 0x02 * 2: hdr-start based pointer to where the scheme starts + length of the scheme (must be Digest). * * for each field present, there are 2 bytes, one pointing the place where it starts, * the next signaling how long this field is. The URI is a special case, and is composed of 1 * byte telling how long is the URI structure, and then the encoded URI structure. */ int encode_digest(char *hdrstart,int hdrlen,dig_cred_t *digest,unsigned char *where) { int i=2,j=0;/* 2*flags */ unsigned char flags1=0,flags2=0; struct sip_uri sipuri; if(digest->username.whole.s && digest->username.whole.len){ flags1|=HAS_NAME_F; where[i++]=(unsigned char)(digest->username.whole.s-hdrstart); where[i++]=(unsigned char)digest->username.whole.len; } if(digest->realm.s && digest->realm.len){ flags1|=HAS_REALM_F; where[i++]=(unsigned char)(digest->realm.s-hdrstart); where[i++]=(unsigned char)digest->realm.len; } if(digest->nonce.s && digest->nonce.len){ flags1|=HAS_NONCE_F; where[i++]=(unsigned char)(digest->nonce.s-hdrstart); where[i++]=(unsigned char)digest->nonce.len; } if(digest->uri.s && digest->uri.len){ memset(&sipuri,0,sizeof(struct sip_uri)); flags1|=HAS_URI_F; if (parse_uri(digest->uri.s, digest->uri.len,&sipuri) < 0 ) { LM_ERR("Bad URI in address\n"); return -1; }else{ if((j=encode_uri2(hdrstart,hdrlen,digest->uri,&sipuri,&where[i+1]))<0){ LM_ERR("Error encoding the URI\n"); return -1; }else{ where[i]=(unsigned char)j; i+=(j+1); } } } if(digest->response.s && digest->response.len){ flags1|=HAS_RESPONSE_F; where[i++]=(unsigned char)(digest->response.s-hdrstart); where[i++]=(unsigned char)digest->response.len; } if(digest->alg.alg_str.s && digest->alg.alg_str.len){ flags1|=HAS_ALG_F; where[i++]=(unsigned char)(digest->alg.alg_str.s-hdrstart); where[i++]=(unsigned char)digest->alg.alg_str.len; } if(digest->cnonce.s && digest->cnonce.len){ flags1|=HAS_CNONCE_F; where[i++]=(unsigned char)(digest->cnonce.s-hdrstart); where[i++]=(unsigned char)digest->cnonce.len; } if(digest->opaque.s && digest->opaque.len){ flags1|=HAS_OPAQUE_F; where[i++]=(unsigned char)(digest->opaque.s-hdrstart); where[i++]=(unsigned char)digest->opaque.len; } if(digest->qop.qop_str.s && digest->qop.qop_str.len){ flags2|=HAS_QoP_F; where[i++]=(unsigned char)(digest->qop.qop_str.s-hdrstart); where[i++]=(unsigned char)digest->qop.qop_str.len; } if(digest->nc.s && digest->nc.len){ flags2|=HAS_NC_F; where[i++]=(unsigned char)(digest->nc.s-hdrstart); where[i++]=(unsigned char)digest->nc.len; } where[0]=flags1; where[1]=flags2; return i; } int print_encoded_digest(FILE *fd,char *hdr,int hdrlen,unsigned char* payload,int paylen,char *prefix) { int i=2;/* flags + flags1 */ unsigned char flags1,flags2; flags1=payload[0]; flags2=payload[1]; fprintf(fd,"%s",prefix); for(i=0;i