FreeRDP/libfreerdp-sspi/Kerberos/kerberos_encode.c
2012-03-05 21:04:42 -05:00

412 lines
9.3 KiB
C

/**
* FreeRDP: A Remote Desktop Protocol Client
* Kerberos Auth Protocol DER Encode
*
* Copyright 2011 Samsung, Author Jiten Pathy
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "kerberos_encode.h"
int krb_encode_sequence_tag(STREAM* s, uint32 len)
{
uint8* bm;
uint32 totlen;
totlen = _GET_BYTE_LENGTH(len + 2) + 1;
stream_rewind(s, totlen);
stream_get_mark(s, bm);
der_write_sequence_tag(s, len);
stream_set_mark(s, bm);
return totlen;
}
int krb_encode_contextual_tag(STREAM* s, uint8 tag, uint32 len)
{
uint8* bm;
uint32 totlen;
totlen = _GET_BYTE_LENGTH(len) + 1;
stream_rewind(s, totlen);
stream_get_mark(s, bm);
der_write_contextual_tag(s, tag, len, true);
stream_set_mark(s, bm);
return totlen;
}
int krb_encode_application_tag(STREAM* s, uint8 tag, uint32 len)
{
uint8* bm;
uint32 totlen;
totlen = _GET_BYTE_LENGTH(len) + 1;
stream_rewind(s, totlen);
stream_get_mark(s, bm);
der_write_application_tag(s, tag, len);
stream_set_mark(s, bm);
return totlen;
}
int krb_encode_recordmark(STREAM* s, uint32 len)
{
uint8* bm;
stream_rewind(s, 4);
stream_get_mark(s, bm);
stream_write_uint32_be(s, len);
stream_set_mark(s, bm);
return 4;
}
int krb_encode_cname(STREAM* s, uint8 tag, char* cname)
{
uint8* bm;
uint32 len;
char* names[2];
names[0] = cname;
names[1] = NULL;
len = strlen(cname) + 15;
stream_rewind(s, len);
stream_get_mark(s, bm);
der_write_contextual_tag(s, tag, len - 2, true);
der_write_principal_name(s, NAME_TYPE_PRINCIPAL, names);
stream_set_mark(s, bm);
return len;
}
int krb_encode_sname(STREAM* s, uint8 tag, char* sname)
{
uint8* bm;
char* str;
char* names[3];
uint32 len, tmp;
len = strlen(sname) - 1 + 17;
stream_rewind(s, len);
stream_get_mark(s, bm);
der_write_contextual_tag(s, tag, len - 2, true);
tmp = strchr(sname, '/') - sname;
str = (char*) xzalloc(tmp + 1);
strncpy(str, sname, tmp);
names[0] = str;
names[1] = sname + tmp + 1;
names[2] = NULL;
der_write_principal_name(s, NAME_TYPE_SERVICE, names);
xfree(str);
stream_set_mark(s, bm);
return len;
}
int krb_encode_uint8(STREAM* s, uint8 tag, uint8 val)
{
uint8* bm;
stream_rewind(s, 5);
stream_get_mark(s, bm);
der_write_contextual_tag(s, tag, 3, true);
der_write_integer(s, val);
stream_set_mark(s, bm);
return 5;
}
int krb_encode_integer(STREAM* s, uint8 tag, int val)
{
uint8* bm;
uint32 totlen;
totlen = der_skip_integer(val);
stream_rewind(s, totlen + 2);
stream_get_mark(s, bm);
der_write_contextual_tag(s, tag, totlen, true);
der_write_integer(s, val);
stream_set_mark(s, bm);
return (totlen + 2);
}
int krb_encode_options(STREAM* s, uint8 tag, uint32 options)
{
uint8* bm;
stream_rewind(s, 9);
stream_get_mark(s, bm);
der_write_contextual_tag(s, tag, 7, true);
der_write_bit_string_tag(s, 5, 0);
stream_write_uint32_be(s, options);
stream_set_mark(s, bm);
return 9;
}
int krb_encode_string(STREAM* s, uint8 tag, char* str)
{
uint8* bm;
uint32 len;
len = strlen(str);
stream_rewind(s, len + 4);
stream_get_mark(s, bm);
der_write_contextual_tag(s, tag, len + 2, true);
der_write_general_string(s, str);
stream_set_mark(s, bm);
return (len + 4);
}
int krb_encode_time(STREAM* s, uint8 tag, char* strtime)
{
uint8* bm;
stream_rewind(s, 19);
stream_get_mark(s, bm);
der_write_contextual_tag(s, tag, 17, true);
der_write_generalized_time(s, strtime);
stream_set_mark(s, bm);
return 19;
}
int krb_encode_octet_string(STREAM* s, uint8* string, uint32 len)
{
uint8* bm;
uint32 totlen;
totlen = len + _GET_BYTE_LENGTH(len) + 1;
stream_rewind(s, totlen);
stream_get_mark(s, bm);
der_write_octet_string(s, string, len);
stream_set_mark(s, bm);
return totlen;
}
int krb_encode_encrypted_data(STREAM* s, KrbENCData* enc_data)
{
uint32 totlen;
/* Encrypted Data[2] */
totlen = krb_encode_octet_string(s, (enc_data->encblob).data, (enc_data->encblob).length);
totlen += krb_encode_contextual_tag(s, 2, totlen);
/* Encrypted key version no[1] */
if(enc_data->kvno != -1)
totlen += krb_encode_uint8(s, 1, enc_data->kvno);
/* Encrypted Type[0] */
totlen += krb_encode_integer(s, 0, enc_data->enctype);
totlen += krb_encode_sequence_tag(s, totlen);
return totlen;
}
int krb_encode_checksum(STREAM* s, rdpBlob* cksum, int cktype)
{
uint32 totlen;
/* Checksum Data[1] */
totlen = krb_encode_octet_string(s, cksum->data, cksum->length);
totlen += krb_encode_contextual_tag(s, 1, totlen);
/* Checksum Type[0] */
totlen += krb_encode_integer(s, 0, cktype);
totlen += krb_encode_sequence_tag(s, totlen);
return totlen;
}
int krb_encode_padata(STREAM* s, PAData** pa_data)
{
uint32 totlen;
uint32 curlen;
PAData** lpa_data;
totlen = 0;
lpa_data = pa_data;
while (*lpa_data != NULL)
{
/* padata value */
curlen = krb_encode_octet_string(s, ((*lpa_data)->value).data, ((*lpa_data)->value).length);
curlen += krb_encode_contextual_tag(s, 2, curlen);
/* padata type */
curlen += krb_encode_integer(s, 1, ((*lpa_data)->type));
curlen += krb_encode_sequence_tag(s, curlen);
totlen += curlen;
lpa_data++;
}
totlen += krb_encode_sequence_tag(s, totlen);
return totlen;
}
int krb_encode_authenticator(STREAM* s, Authenticator *krb_auth)
{
uint8* bm;
uint32 totlen, curlen;
/* seq no[7] */
stream_rewind(s, 8);
stream_get_mark(s, bm);
der_write_contextual_tag(s, 7, 6, true);
der_write_integer(s, krb_auth->seqno);
totlen = 8;
stream_set_mark(s, bm);
/* ctime[5] */
totlen += krb_encode_time(s, 5, krb_auth->ctime);
/* cusec[4] */
totlen += krb_encode_integer(s, 4, krb_auth->cusec);
/* cksum[3] */
curlen = krb_encode_checksum(s, krb_auth->cksum, krb_auth->cksumtype);
totlen += krb_encode_contextual_tag(s, 3, curlen) + curlen;
/* cname[2] */
totlen += krb_encode_cname(s, 2, krb_auth->cname);
/* crealm[1] */
totlen += krb_encode_string(s, 1, krb_auth->crealm);
/* avno[0] */
totlen += krb_encode_uint8(s, 0, krb_auth->avno);
totlen += krb_encode_sequence_tag(s, totlen);
totlen += krb_encode_application_tag(s, 2, totlen);
return totlen;
}
int krb_encode_ticket(STREAM* s, uint8 tag, Ticket* ticket)
{
uint32 totlen;
/* Encrypted DATA[3] */
totlen = krb_encode_encrypted_data(s, &(ticket->enc_part));
totlen += krb_encode_contextual_tag(s, 3, totlen);
/* sname[2] */
totlen += krb_encode_sname(s, 2, ticket->sname);
/* realm[1] */
totlen += krb_encode_string(s, 1, ticket->realm);
/* ticket vno[0] */
totlen += krb_encode_uint8(s, 0, ticket->tktvno);
totlen += krb_encode_sequence_tag(s, totlen);
totlen += krb_encode_application_tag(s, 1, totlen);
totlen += krb_encode_contextual_tag(s, tag, totlen);
return totlen;
}
int krb_encode_req_body(STREAM* s, KDCReqBody* req_body, int msgtype)
{
uint8* bm;
uint32 totlen;
totlen = 0;
/* ETYPE[8] we support des-cbc-crc, rc4-hmac and aes-128-ctc-hmac-sha1-96 only */
stream_rewind(s, 10);
stream_get_mark(s, bm);
der_write_contextual_tag(s, 8, 8, true);
der_write_sequence_tag(s, 6);
der_write_integer(s, ETYPE_RC4_HMAC);
der_write_integer(s, ETYPE_DES_CBC_CRC);
totlen += 10;
stream_set_mark(s, bm);
/* NONCE[7] */
stream_rewind(s, 8);
stream_get_mark(s, bm);
der_write_contextual_tag(s, 7, 6, true);
der_write_integer(s, req_body->nonce);
totlen += 8;
stream_set_mark(s, bm);
/* till[5] and rtime (tag 6)*/
totlen += krb_encode_time(s, 6, req_body->rtime);
totlen += krb_encode_time(s, 5, req_body->till);
/* SNAME[3]*/
totlen += krb_encode_sname(s, 3, req_body->sname);
/* REALM[2] */
totlen += krb_encode_string(s, 2, req_body->realm);
/* CNAME[1] */
totlen += krb_encode_cname(s, 1, req_body->cname);
/* KDCOptions[0]*/
totlen += krb_encode_options(s, 0, req_body->kdc_options);
/* KDC_BODY */
totlen += krb_encode_sequence_tag(s, totlen);
return totlen;
}
int krb_encode_apreq(STREAM* s, KrbAPREQ* krb_apreq)
{
uint32 totlen;
/* Encrypted Authenticator[4] */
totlen = krb_encode_encrypted_data(s, &(krb_apreq->enc_auth));
totlen += krb_encode_contextual_tag(s, 4, totlen);
/* Ticket[3] */
totlen += krb_encode_ticket(s, 3, krb_apreq->ticket);
/* APOPTIONS[2] */
totlen += krb_encode_options(s, 2, krb_apreq->ap_options);
/* MSGTYPE[1] */
totlen += krb_encode_uint8(s , 1, krb_apreq->type);
/* VERSION NO[0] */
totlen += krb_encode_uint8(s, 0, krb_apreq->pvno);
totlen += krb_encode_sequence_tag(s, totlen);
totlen += krb_encode_application_tag(s, krb_apreq->type, totlen);
return totlen;
}
int krb_encode_tgtreq(STREAM* s, KrbTGTREQ* krb_tgtreq)
{
uint32 totlen;
totlen = 0;
/* realm[3] optional */
if(krb_tgtreq->realm != NULL)
totlen += krb_encode_string(s, 3, krb_tgtreq->realm);
/* sname[2] optional */
if(krb_tgtreq->sname != NULL)
totlen += krb_encode_sname(s, 3, krb_tgtreq->sname);
/* msgtype[1] */
totlen += krb_encode_uint8(s , 1, krb_tgtreq->type);
/* pvno[0] */
totlen += krb_encode_uint8(s, 0, krb_tgtreq->pvno);
totlen += krb_encode_sequence_tag(s, totlen);
return totlen;
}