libfreerdp-auth: integrate Kerberos code from Jiten Pathy

This commit is contained in:
Marc-André Moreau 2012-03-05 16:57:25 -05:00
parent 386d815969
commit 6582dd3ebf
14 changed files with 3224 additions and 4 deletions

View File

@ -276,7 +276,9 @@ struct rdp_settings
boolean compression; /* 59 */ boolean compression; /* 59 */
uint32 performance_flags; /* 60 */ uint32 performance_flags; /* 60 */
rdpBlob* password_cookie; /* 61 */ rdpBlob* password_cookie; /* 61 */
uint32 paddingC[80 - 62]; /* 62 */ char* kerberos_kdc; /* 62 */
char* kerberos_realm; /* 63 */
uint32 paddingC[80 - 64]; /* 64 */
/* User Interface Parameters */ /* User Interface Parameters */
boolean sw_gdi; /* 80 */ boolean sw_gdi; /* 80 */

View File

@ -20,6 +20,7 @@
#ifndef __BLOB_UTILS_H #ifndef __BLOB_UTILS_H
#define __BLOB_UTILS_H #define __BLOB_UTILS_H
#include <string.h>
#include <freerdp/api.h> #include <freerdp/api.h>
struct rdp_blob struct rdp_blob
@ -31,5 +32,6 @@ typedef struct rdp_blob rdpBlob;
FREERDP_API void freerdp_blob_alloc(rdpBlob* blob, int length); FREERDP_API void freerdp_blob_alloc(rdpBlob* blob, int length);
FREERDP_API void freerdp_blob_free(rdpBlob* blob); FREERDP_API void freerdp_blob_free(rdpBlob* blob);
FREERDP_API void freerdp_blob_copy(rdpBlob* dstblob, rdpBlob* srcblob);
#endif /* __BLOB_UTILS_H */ #endif /* __BLOB_UTILS_H */

View File

@ -21,6 +21,7 @@
#define __MEMORY_UTILS_H #define __MEMORY_UTILS_H
#include <stddef.h> #include <stddef.h>
#include <ctype.h>
#include <freerdp/api.h> #include <freerdp/api.h>
FREERDP_API void* xmalloc(size_t size); FREERDP_API void* xmalloc(size_t size);
@ -28,6 +29,7 @@ FREERDP_API void* xzalloc(size_t size);
FREERDP_API void* xrealloc(void* ptr, size_t size); FREERDP_API void* xrealloc(void* ptr, size_t size);
FREERDP_API void xfree(void* ptr); FREERDP_API void xfree(void* ptr);
FREERDP_API char* xstrdup(const char* str); FREERDP_API char* xstrdup(const char* str);
FREERDP_API char* xstrtoup(const char* str);
#define xnew(_type) (_type*)xzalloc(sizeof(_type)) #define xnew(_type) (_type*)xzalloc(sizeof(_type))

View File

@ -17,13 +17,27 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
set(FREERDP_AUTH_SRCS set(FREERDP_SSPI_NTLM_SRCS
NTLM/ntlm.c
NTLM/ntlm.h
NTLM/ntlm_compute.c NTLM/ntlm_compute.c
NTLM/ntlm_compute.h NTLM/ntlm_compute.h
NTLM/ntlm_message.c NTLM/ntlm_message.c
NTLM/ntlm_message.h NTLM/ntlm_message.h
NTLM/ntlm.c
NTLM/ntlm.h)
set(FREERDP_SSPI_KERBEROS_SRCS
Kerberos/kerberos_crypto.c
Kerberos/kerberos_crypto.h
Kerberos/kerberos_decode.c
Kerberos/kerberos_decode.h
Kerberos/kerberos_encode.c
Kerberos/kerberos_encode.h
Kerberos/kerberos.c
Kerberos/kerberos.h)
set(FREERDP_AUTH_SRCS
${FREERDP_SSPI_NTLM_SRCS}
${FREERDP_SSPI_KERBEROS_SRCS}
sspi.c sspi.c
sspi.h sspi.h
credssp.c) credssp.c)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,347 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* Kerberos Auth Protocol
*
* 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.
*/
#ifndef __FREERDP_KRB_H
#define __FREERDP_KRB_H
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/nameser.h>
#include <resolv.h>
#ifdef _WIN32
#include <winsock2.h>
#include <Windows.h>
#include <ws2tcpip.h>
#endif
#include <freerdp/auth/sspi.h>
#include <freerdp/types.h>
#include <freerdp/settings.h>
#include <freerdp/utils/stream.h>
#include <freerdp/utils/blob.h>
#define MSKRB_OID "1.2.840.48018.1.2.2"
#define STDKRB_OID "1.2.840.113554.1.2.2"
#define SERVICE "_kerberos."
#define KRB_VERSION 5
#define KRB_SERVER "krbtgt/"
#define APP_SERVER "TERMSRV/"
#define KRB_NAME_PRINCIPAL 1
#define KRB_NAME_SERVICE 2
/* KRB TAGS */
#define KRB_TAG_ASREQ 10
#define KRB_TAG_ASREP 11
#define KRB_TAG_TGSREQ 12
#define KRB_TAG_TGSREP 13
#define KRB_TAG_APREQ 14
#define KRB_TAG_APREP 15
#define KRB_TAG_ERROR 30
#define KRB_TAG_U2UTGTREQ 16
#define KRB_TAG_U2UTGTREP 16
#define NAME_TYPE_PRINCIPAL 1
#define NAME_TYPE_SERVICE 2
/* KRB ERROR */
#define KDC_ERR_PREAUTH_FAILED 24
#define KDC_ERR_PREAUTH_REQ 25
#define KRB_AP_ERR_SKEW 37
#define KDC_ERR_C_PRINCIPAL_UNKNOWN 6
#define PA_ENCTYPE_INFO 11
#define PA_ENCTYPE_INFO2 19
/* ENCRYPTION TYPE */
#define ETYPE_DES_CBC_CRC 1
#define ETYPE_DES_CBC_MD5 3
#define ETYPE_AES128_CTS_HMAC 17
#define ETYPE_AES256_CTS_HMAC 18
#define ETYPE_RC4_HMAC 23
/* CHECKSUM TYPE */
#define KRB_CKSUM_HMAC_MD5 -138
/* AD TYPE */
#define AD_IF_RELEVANT 1
#define GETUINT16( _s, _p) do{ \
*(_p) = (uint8)(_s)[0] << 8 | (uint8)(_s)[1]; \
(_s) += 2; } while (0)
#define _GET_BYTE_LENGTH(_n) (((_n) > 0xFF) ? 3 :(((_n) > 0x7F) ? 2 : 1))
enum _KRBCTX_STATE
{
KRB_STATE_INITIAL,
KRB_FAILOVER_NTLM,
KRB_ASREQ_OK,
KRB_ASREP_OK,
KRB_ASREP_ERR,
KRB_TGSREQ_OK,
KRB_TGSREP_OK,
KRB_TGSREP_ERR,
KRB_U2UTGTREQ_OK,
KRB_U2UTGTREP_OK,
KRB_APREQ_OK,
KRB_APREP_OK,
KRB_PACKET_ERROR,
KRB_STATE_FINAL
};
typedef enum _KRBCTX_STATE KRBCTX_STATE;
struct _kdc_srv_entry
{
struct _kdc_srv_entry* next;
uint16 priority;
uint16 weight;
uint16 port;
char* kdchost;
};
typedef struct _kdc_srv_entry KDCENTRY;
struct _PA_DATA
{
int type;
rdpBlob value;
};
typedef struct _PA_DATA PAData;
struct _AUTH_DATA
{
int ad_type;
uint8* ad_data;
};
typedef struct _AUTH_DATA AuthData;
struct _Krb_ENCData
{
sint32 enctype;
int kvno;
rdpBlob encblob;
};
typedef struct _Krb_ENCData KrbENCData;
struct _Krb_ENCKey
{
sint32 enctype;
rdpBlob skey;
};
typedef struct _Krb_ENCKey KrbENCKey;
struct _ENC_KDC_REPPART
{
KrbENCKey key;
int nonce;
uint32 flags;
uint32 authtime;
uint32 endtime;
char *realm;
char *sname;
};
typedef struct _ENC_KDC_REPPART ENCKDCREPPart;
struct _Krb_Ticket
{
int tktvno;
char* realm;
char* sname;
KrbENCData enc_part;
};
typedef struct _Krb_Ticket Ticket;
struct _Krb_Authenticator
{
int avno;
char* crealm;
char* cname;
int cksumtype;
rdpBlob* cksum;
uint32 cusec;
char* ctime;
uint32 seqno;
AuthData auth_data;
};
typedef struct _Krb_Authenticator Authenticator;
struct _KDC_REQ_BODY
{
uint32 kdc_options;
char* cname;
char* realm;
char* sname;
char* from;
char* till;
char* rtime;
uint32 nonce;
};
typedef struct _KDC_REQ_BODY KDCReqBody;
struct _KRB_KDCREP
{
int pvno;
int type;
PAData** padata;
char* realm;
char* cname;
Ticket etgt;
KrbENCData enc_part;
};
typedef struct _KRB_KDCREP KrbKDCREP;
struct _KRB_AS_REQ
{
int pvno;
int type;
boolean pa_pac_request;
PAData** padata;
KDCReqBody req_body;
};
typedef struct _KRB_AS_REQ KrbASREQ;
struct _KRB_TGS_REQ
{
int pvno;
int type;
boolean pa_pac_request;
PAData** padata;
KDCReqBody req_body;
};
typedef struct _KRB_TGS_REQ KrbTGSREQ;
struct _KRB_APREQ
{
int pvno;
int type;
uint32 ap_options;
Ticket* ticket;
KrbENCData enc_auth;
};
typedef struct _KRB_APREQ KrbAPREQ;
struct _KRB_ERROR
{
int pvno;
int type;
int errcode;
char* stime;
uint32 susec;
char* realm;
char* sname;
rdpBlob edata;
};
typedef struct _KRB_ERROR KrbERROR;
struct _KRB_ASREP
{
KrbKDCREP kdc_rep;
};
typedef struct _KRB_ASREP KrbASREP;
struct _KRB_TGSREP
{
KrbKDCREP kdc_rep;
};
typedef struct _KRB_TGSREP KrbTGSREP;
struct _KRB_TGTREQ
{
int pvno;
int type;
char* sname;
char* realm;
};
typedef struct _KRB_TGTREQ KrbTGTREQ;
struct _KRB_TGTREP
{
int pvno;
int type;
Ticket ticket;
};
typedef struct _KRB_TGTREP KrbTGTREP;
struct _KRB_CONTEXT
{
UNICONV* uniconv;
rdpSettings* settings;
int ksockfd;
uint16 krbport;
char* krbhost;
char* cname;
char* realm;
char* sname;
char* hostname;
SEC_AUTH_IDENTITY identity;
rdpBlob passwd;
sint32 enctype;
sint32 clockskew;
uint32 ctime;
uint32 nonce;
Ticket asticket;
KrbENCKey* askey;
Ticket tgsticket;
KrbENCKey* tgskey;
KRBCTX_STATE state;
CTXT_HANDLE context;
};
typedef struct _KRB_CONTEXT KRB_CONTEXT;
CTXT_HANDLE* krbctx_client_init(rdpSettings* settings, SEC_AUTH_IDENTITY* identity);
boolean tcp_is_ipaddr(const char* hostname);
char* get_utc_time(time_t t);
time_t get_local_time(char* str);
uint32 get_clock_skew(char* str);
char* get_dns_queryname(char *host, char* protocol);
int krb_get_realm(rdpSettings* settings);
KDCENTRY* krb_locate_kdc(rdpSettings* settings);
int krb_tcp_connect(KRB_CONTEXT* krb_ctx, KDCENTRY* entry);
int krb_tcp_send(KRB_CONTEXT* krb_ctx, uint8* data, uint32 length);
int krb_tcp_recv(KRB_CONTEXT* krb_ctx, uint8* data, uint32 length);
void krb_asreq_send(KRB_CONTEXT* krb_ctx, uint8 errcode);
int krb_asrep_recv(KRB_CONTEXT* krb_ctx);
void krb_tgsreq_send(KRB_CONTEXT* krb_ctx, uint8 errcode);
int krb_tgsrep_recv(KRB_CONTEXT* krb_ctx);
int krb_verify_kdcrep(KRB_CONTEXT* krb_ctx, KrbKDCREP* kdc_rep, int msgtype);
void krb_save_ticket(KRB_CONTEXT* krb_ctx, KrbKDCREP* kdc_rep);
KrbASREQ* krb_asreq_new(KRB_CONTEXT* krb_ctx, uint8 errcode);
KrbTGSREQ* krb_tgsreq_new(KRB_CONTEXT* krb_Rss, uint8 errcode);
KrbAPREQ* krb_apreq_new(KRB_CONTEXT* krb_ctx, Ticket* ticket, Authenticator* krb_auth);
void krb_ContextFree(KRB_CONTEXT* krb_ctx);
void krb_free_ticket(Ticket* ticket);
void krb_free_padata(PAData** padata);
void krb_free_req_body(KDCReqBody* req_body);
void krb_free_kdcrep(KrbKDCREP* kdc_rep);
void krb_free_reppart(ENCKDCREPPart* reppart);
void krb_free_asreq(KrbASREQ* krb_asreq);
void krb_free_asrep(KrbASREP* krb_asrep);
void krb_free_tgsreq(KrbTGSREQ* krb_tgsreq);
void krb_free_tgsrep(KrbTGSREP* krb_tgsrep);
void krb_free_krb_error(KrbERROR* krb_err);
#endif /* __FREERDP_KRB_H */

View File

@ -0,0 +1,174 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* kerberos Crypto Support
*
* 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.h"
#include "kerberos_crypto.h"
uint8* crypto_md4_hash(rdpBlob* blob)
{
MD4_CTX md4_ctx;
uint8* hash;
hash = (uint8*)xzalloc(16);
MD4_Init(&md4_ctx);
MD4_Update(&md4_ctx, blob->data, blob->length);
MD4_Final(hash, &md4_ctx);
return hash;
}
KrbENCKey* string2key(rdpBlob* string, sint8 enctype)
{
KrbENCKey* key;
key = xnew(KrbENCKey);
key->enctype = enctype;
switch(enctype)
{
case ETYPE_RC4_HMAC:
key->skey.data = crypto_md4_hash(string);
key->skey.length = 16;
break;
}
return key;
}
rdpBlob* crypto_kdcmsg_encrypt_rc4(rdpBlob* msg, uint8* key, uint32 msgtype)
{
rdpBlob* encmsg;
uint8* K1;
uint8* K3;
uint32 len;
krbEdata* edata;
CryptoRc4 rc4;
K1 = xzalloc(16);
K3 = xzalloc(16);
len = ((msg->length > 16) ? msg->length : 16);
len += sizeof(krbEdata);
edata = xzalloc(len);
encmsg = xnew(rdpBlob);
freerdp_blob_alloc(encmsg, len);
HMAC(EVP_md5(), (void*) key, 16, (uint8*)&msgtype, 4, (void*) K1, NULL);
crypto_nonce((uint8*)(edata->Confounder), 8);
memcpy(&(edata->data[0]), msg->data, msg->length);
HMAC(EVP_md5(), (void*) K1, 16, (uint8*)edata->Confounder, len - 16, (void*)&(edata->Checksum), NULL);
HMAC(EVP_md5(), (void*) K1, 16, (uint8*)&(edata->Checksum), 16, (void*)K3, NULL);
memcpy(encmsg->data, &(edata->Checksum), 16);
rc4 = crypto_rc4_init(K3, 16);
crypto_rc4(rc4, len - 16, (uint8*)edata->Confounder, (uint8*)(encmsg->data + 16));
crypto_rc4_free(rc4);
xfree(K1);
xfree(K3);
xfree(edata);
return encmsg;
}
rdpBlob* crypto_kdcmsg_encrypt(rdpBlob* msg, KrbENCKey* key, uint32 msgtype)
{
switch(key->enctype)
{
case ETYPE_RC4_HMAC:
if(key->skey.length != 16)
return NULL;
return crypto_kdcmsg_encrypt_rc4(msg, key->skey.data, msgtype);
}
return NULL;
}
rdpBlob* crypto_kdcmsg_decrypt_rc4(rdpBlob* msg, uint8* key, uint32 msgtype)
{
rdpBlob* decmsg;
uint8* K1;
uint8* K3;
uint32 len;
krbEdata* edata;
CryptoRc4 rc4;
K1 = xzalloc(16);
K3 = xzalloc(16);
len = msg->length;
edata = xzalloc(len);
HMAC(EVP_md5(), (void*) key, 16, (uint8*)&msgtype, 4, (void*) K1, NULL);
HMAC(EVP_md5(), (void*) K1, 16, msg->data , 16, (void*)K3, NULL);
rc4 = crypto_rc4_init(K3, 16);
crypto_rc4(rc4, len - 16, (uint8*)(msg->data + 16), (uint8*)edata->Confounder);
crypto_rc4_free(rc4);
HMAC(EVP_md5(), (void*) K1, 16, (uint8*)edata->Confounder, len - 16, (void*)&(edata->Checksum), NULL);
if(memcmp(msg->data, &edata->Checksum, 16))
return NULL;
decmsg = xnew(rdpBlob);
freerdp_blob_alloc(decmsg, len);
memcpy(decmsg->data, edata, len);
xfree(K1);
xfree(K3);
xfree(edata);
return decmsg;
}
rdpBlob* crypto_kdcmsg_decrypt(rdpBlob* msg, KrbENCKey* key, uint32 msgtype)
{
switch(key->enctype)
{
case ETYPE_RC4_HMAC:
if(key->skey.length != 16)
return NULL;
return crypto_kdcmsg_decrypt_rc4(msg, key->skey.data, msgtype);
}
return NULL;
}
rdpBlob* crypto_kdcmsg_cksum_hmacmd5(rdpBlob* msg, uint8* key, uint32 msgtype)
{
rdpBlob* cksum;
uint8* Ksign;
uint8* tmpdata;
uint8* tmp;
CryptoMd5 md5;
Ksign = xzalloc(16);
tmp = xzalloc(16);
cksum = xnew(rdpBlob);
freerdp_blob_alloc(cksum, 16);
tmpdata = xzalloc(msg->length + 4);
HMAC(EVP_md5(), (void*) key, 16, (uint8*)"signaturekey\0", 13, (void*) Ksign, NULL);
memcpy(tmpdata, (void*)&msgtype, 4);
memcpy(tmpdata + 4, msg->data, msg->length);
md5 = crypto_md5_init();
crypto_md5_update(md5, tmpdata, msg->length + 4);
crypto_md5_final(md5, tmp);
HMAC(EVP_md5(), (void*) Ksign, 16, (uint8*)tmp, 16, (void*) cksum->data, NULL);
return cksum;
}
rdpBlob* crypto_kdcmsg_cksum(rdpBlob* msg, KrbENCKey* key, uint32 msgtype)
{
switch(key->enctype)
{
case ETYPE_RC4_HMAC:
if(key->skey.length != 16)
return NULL;
return crypto_kdcmsg_cksum_hmacmd5(msg, key->skey.data, msgtype);
}
return NULL;
}
int get_cksum_type(uint32 enctype)
{
switch(enctype)
{
case ETYPE_RC4_HMAC:
return KRB_CKSUM_HMAC_MD5;
}
return 0;
}

View File

@ -0,0 +1,56 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* kerberos Crypto Support
*
* 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.
*/
#ifndef __KRB_CRYPTO_H
#define __KRB_CRYPTO_H
#include <openssl/err.h>
#include <openssl/rc4.h>
#include <openssl/md4.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/bn.h>
#include <openssl/rand.h>
#include <freerdp/crypto/crypto.h>
struct _KRB_EDATA
{
uint8 Checksum[16];
uint8 Confounder[8];
uint8* data[0];
};
typedef struct _KRB_EDATA krbEdata;
int get_cksum_type(uint32 enctype);
uint8* crypto_md4_hash(rdpBlob* blob);
KrbENCKey* string2key(rdpBlob* string, sint8 enctype);
rdpBlob* crypto_kdcmsg_encrypt_rc4(rdpBlob* msg, uint8* key, uint32 msgtype);
rdpBlob* crypto_kdcmsg_encrypt(rdpBlob* msg, KrbENCKey* key, uint32 msgtype);
rdpBlob* crypto_kdcmsg_decrypt_rc4(rdpBlob* msg, uint8* key, uint32 msgtype);
rdpBlob* crypto_kdcmsg_decrypt(rdpBlob* msg, KrbENCKey* key, uint32 msgtype);
rdpBlob* crypto_kdcmsg_cksum_hmacmd5(rdpBlob* msg, uint8* key, uint32 msgtype);
rdpBlob* crypto_kdcmsg_cksum(rdpBlob* msg, KrbENCKey* key, uint32 msgtype);
#endif /* __KRB_CRYPTO_H */

View File

@ -0,0 +1,834 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* Kerberos Auth Protocol DER Decode
*
* 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_decode.h"
int krb_decode_application_tag(STREAM* s, uint8 tag, int *length)
{
uint8* bm;
stream_get_mark(s, bm);
if(!der_read_application_tag(s, tag, length))
{
stream_set_mark(s, bm);
*length = 0;
return 0;
}
return (s->p - bm);
}
int krb_decode_sequence_tag(STREAM* s, int *length)
{
uint8* bm;
stream_get_mark(s, bm);
if(!der_read_sequence_tag(s, length))
{
stream_set_mark(s, bm);
*length = 0;
return 0;
}
return (s->p - bm);
}
int krb_decode_contextual_tag(STREAM* s, uint8 tag, int *length)
{
uint8* bm;
stream_get_mark(s, bm);
if(!der_read_contextual_tag(s, tag, length, true))
{
stream_set_mark(s, bm);
*length = 0;
return 0;
}
return (s->p - bm);
}
int krb_skip_contextual_tag(STREAM* s, uint8 tag)
{
uint8* bm;
int length;
stream_get_mark(s, bm);
if(!der_read_contextual_tag(s, tag, &length, true))
{
stream_set_mark(s, bm);
length = 0;
return 0;
}
stream_seek(s, length);
return (s->p - bm);
}
int krb_decode_integer(STREAM* s, uint32* value)
{
uint8* bm;
stream_get_mark(s, bm);
if(!der_read_integer(s, value))
{
stream_set_mark(s, bm);
*value = 0;
return 0;
}
else
return (s->p - bm);
}
int krb_decode_time(STREAM* s, uint8 tag, char** str)
{
uint8* bm;
int tmp;
stream_get_mark(s, bm);
if((krb_decode_contextual_tag(s, tag, &tmp) == 0) || (tmp != 17) || !der_read_generalized_time(s, str))
{
stream_set_mark(s, bm);
return 0;
}
else
return (s->p - bm);
}
int krb_decode_int(STREAM* s, uint8 tag, uint32* result)
{
uint8* bm;
int totlen, len, tmp;
totlen = 0;
stream_get_mark(s, bm);
if((len = krb_decode_contextual_tag(s, tag, &tmp)) == 0)
goto err;
totlen += len;
if(((len = krb_decode_integer(s, result)) == 0) || (tmp != len))
goto err;
totlen += len;
return totlen;
err:
stream_set_mark(s, bm);
*result = 0;
return 0;
}
int krb_decode_flags(STREAM* s, uint8 tag, uint32* flags)
{
uint8* bm;
int len, tmp, verlen;
verlen = 9;
stream_get_mark(s, bm);
if(((len = krb_decode_contextual_tag(s, tag, &tmp)) == 0) || (len != (verlen - tmp)))
goto err;
verlen -= len;
if(!der_read_bit_string(s, &tmp, (uint8*)&len) || (tmp != 5))
goto err;
stream_read_uint32_be(s, *flags);
return 9;
err:
stream_set_mark(s, bm);
return 0;
}
int krb_decode_string(STREAM* s, uint8 tag, char** str)
{
uint8* bm;
int totlen, len, tmp;
totlen = 0;
stream_get_mark(s, bm);
if((len = krb_decode_contextual_tag(s, tag, &tmp)) == 0)
goto err;
totlen += len;
if(((*str = der_read_general_string(s, &len)) == NULL) || tmp != len)
goto err;
totlen += len;
return totlen;
err:
stream_set_mark(s, bm);
return 0;
}
int krb_decode_octet_string(STREAM* s, uint8 tag, uint8** data, int* length)
{
uint8* bm;
int totlen, len, tmp, verlen;
totlen = 0;
stream_get_mark(s, bm);
if((len = krb_decode_contextual_tag(s, tag, &verlen)) == 0)
goto err;
totlen += len;
if(!der_read_octet_string(s, &tmp))
{
stream_set_mark(s, bm);
*length = 0;
return 0;
}
totlen += tmp + _GET_BYTE_LENGTH(tmp) + 1;
verlen -= (tmp + _GET_BYTE_LENGTH(tmp) + 1);
if(verlen != 0)
goto err;
*data = xzalloc(tmp);
stream_read(s, *data, tmp);
*length = tmp;
return totlen;
err:
stream_set_mark(s, bm);
return 0;
}
int krb_decode_cname(STREAM* s, uint8 tag, char** str)
{
uint8* bm;
int totlen, len, tmp, type, verlen;
totlen = 0;
stream_get_mark(s, bm);
/* Contextual tag */
if((len = krb_decode_contextual_tag(s, tag, &verlen)) == 0)
goto err;
totlen += len;
/* cname sequence tag */
if(((len = krb_decode_sequence_tag(s, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
totlen += len;
verlen -= len;
/* cname name type[0] */
if((verlen <= 0) || ((len = krb_decode_int(s, 0, (uint32*)&type)) == 0) || (type != KRB_NAME_PRINCIPAL))
goto err;
totlen += len;
verlen -= len;
/* cname name[1] */
if((verlen <= 0) || ((len = krb_decode_contextual_tag(s, 1, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
totlen += len;
verlen -= len;
if((verlen <= 0) || ((len = krb_decode_sequence_tag(s, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
totlen += len;
verlen -= len;
if(((*str = der_read_general_string(s, &len)) == NULL))
goto err;
totlen += len;
if(verlen != len)
{
xfree(str);
*str = NULL;
goto err;
}
return totlen;
err:
stream_set_mark(s, bm);
return 0;
}
int krb_decode_sname(STREAM* s, uint8 tag, char** str)
{
uint8* bm;
int totlen, len, tmp, type, verlen;
char* name;
char* realm;
totlen = 0;
stream_get_mark(s, bm);
/* Contextual tag */
if((len = krb_decode_contextual_tag(s, tag, &verlen)) == 0)
goto err;
totlen += len;
/* sname sequence tag */
if(((len = krb_decode_sequence_tag(s, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
totlen += len;
verlen -= len;
/* sname name type[0] */
if((verlen <= 0) || ((len = krb_decode_int(s, 0, (uint32*)&type)) == 0) || (type != KRB_NAME_SERVICE))
goto err;
totlen += len;
verlen -= len;
/* sname name & realm[1] */
if((verlen <= 0) || ((len = krb_decode_contextual_tag(s, 1, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
totlen += len;
verlen -= len;
if((verlen <= 0) || ((len = krb_decode_sequence_tag(s, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
totlen += len;
verlen -= len;
if(((name = der_read_general_string(s, &len)) == NULL))
goto err;
totlen += len;
verlen -= len;
if(((realm = der_read_general_string(s, &len)) == NULL))
{
xfree(name);
goto err;
}
totlen += len;
if(verlen != len)
{
xfree(name);
xfree(realm);
goto err;
}
*str = xzalloc(strlen(name) + strlen(realm) + 2);
strcpy(*str, name);
strcat(*str, "/");
strcat(*str, realm);
xfree(name);
xfree(realm);
return totlen;
err:
stream_set_mark(s, bm);
return 0;
}
int krb_decode_enckey(STREAM* s, KrbENCKey* key)
{
uint8* bm;
int totlen, len, verlen;
totlen = 0;
stream_get_mark(s, bm);
if((len = krb_decode_sequence_tag(s, &verlen)) == 0)
goto err;
totlen += len;
/* enctype[0] */
if((len = krb_decode_int(s, 0, (uint32*)&(key->enctype))) == 0)
goto err;
totlen += len;
verlen -= len;
/* keyvalue[1] */
if((verlen <= 0) || ((len = krb_decode_octet_string(s, 1, (uint8**)&(key->skey.data), &(key->skey.length))) == 0))
goto err;
totlen += len;
if(verlen != len)
goto err;
return totlen;
err:
stream_set_mark(s, bm);
return 0;
}
int krb_decode_encrypted_data(STREAM* s, KrbENCData* enc_data)
{
uint8* bm;
int totlen, len, verlen;
totlen = 0;
stream_get_mark(s, bm);
if((len = krb_decode_sequence_tag(s, &verlen)) == 0)
goto err;
totlen += len;
/* enctype[0] */
if(((len = krb_decode_int(s, 0, (uint32*)&(enc_data->enctype))) == 0))
goto err;
totlen += len;
verlen -= len;
/* kvno[1] OPTIONAL */
if((verlen <= 0))
goto err;
len = krb_decode_int(s, 1, (uint32*)&(enc_data->kvno));
totlen += len;
verlen -= len;
/* data[2] */
if((verlen <= 0) || ((len = krb_decode_octet_string(s, 2, (uint8**)&(enc_data->encblob.data), &(enc_data->encblob.length))) == 0))
goto err;
totlen += len;
if(verlen != len)
goto err;
return totlen;
err:
stream_set_mark(s, bm);
return 0;
}
int krb_decode_ticket(STREAM* s, uint8 tag, Ticket* ticket)
{
uint8* bm;
int totlen, len, tmp, verlen;
totlen = 0;
stream_get_mark(s, bm);
/* Contextual tag */
if((len = krb_decode_contextual_tag(s, tag, &verlen)) == 0)
goto err;
totlen += len;
/* Application Tag 1 */
if(((len = krb_decode_application_tag(s, 1, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
totlen += len;
verlen -=len;
if((verlen <= 0) || ((len = krb_decode_sequence_tag(s, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
totlen += len;
verlen -= len;
/* tkt vno[0] */
if((verlen <= 0) || ((len = krb_decode_int(s, 0, (uint32*)&(ticket->tktvno))) == 0))
goto err;
totlen += len;
verlen -= len;
/* realm[1] */
if((verlen <= 0) || ((len = krb_decode_string(s, 1, &(ticket->realm))) == 0))
goto err;
totlen += len;
verlen -= len;
/* sname[2] */
if((verlen <= 0) || ((len = krb_decode_sname(s, 2, &(ticket->sname))) == 0))
goto err;
totlen += len;
verlen -= len;
/* Encrypted Data[3] */
if((verlen <= 0) || ((len = krb_decode_contextual_tag(s, 3, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
totlen += len;
verlen -= len;
if((verlen <= 0) || ((len = krb_decode_encrypted_data(s, &(ticket->enc_part))) == 0))
goto err;
totlen += len;
if(verlen != len)
goto err;
return totlen;
err:
stream_set_mark(s, bm);
krb_free_ticket(ticket);
return 0;
}
int krb_decode_kdc_rep(STREAM* s, KrbKDCREP* kdc_rep, sint32 maxlen)
{
uint8* bm;
int totlen, len, tmp, verlen;
totlen = 0;
stream_get_mark(s, bm);
/* sequence tag */
if(((len = krb_decode_sequence_tag(s, &verlen)) == 0) || (verlen != (maxlen - len)))
goto err;
totlen += len;
/* version no[0] */
if(((len = krb_decode_int(s, 0, (uint32*)&(kdc_rep->pvno))) == 0))
goto err;
totlen += len;
verlen -= len;
/* msg type[1] */
if((verlen <= 0) || ((len = krb_decode_int(s, 1, (uint32*)&(kdc_rep->type))) == 0))
goto err;
totlen += len;
verlen -= len;
/* PA-DATA[2] OPTIONAL */
if(verlen <= 0)
goto err;
len = krb_decode_contextual_tag(s, 2, &tmp);
totlen += len + tmp;
verlen -= (len + tmp);
stream_seek(s, tmp);
/* crealm[3] */
if((verlen <= 0) || ((len = krb_decode_string(s, 3, &(kdc_rep->realm))) == 0))
goto err;
totlen += len;
verlen -= len;
/* cname[4] */
if((verlen <= 0) || ((len = krb_decode_cname(s, 4, &(kdc_rep->cname))) == 0))
goto err;
totlen += len;
verlen -= len;
/* ticket[5] */
if((verlen <= 0) || ((len = krb_decode_ticket(s, 5, &(kdc_rep->etgt))) == 0))
goto err;
totlen += len;
verlen -= len;
/* enc_part[6] */
if((verlen <= 0) || ((len = krb_decode_contextual_tag(s, 6, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
totlen += len;
verlen -= len;
if((verlen <= 0) || ((len = krb_decode_encrypted_data(s, &(kdc_rep->enc_part))) == 0))
goto err;
totlen += len;
if(verlen != len)
goto err;
return totlen;
err:
krb_free_kdcrep(kdc_rep);
return 0;
}
int krb_decode_krb_error(STREAM* s, KrbERROR* krb_err, sint32 maxlen)
{
uint8* bm;
int totlen, len, verlen;
int i, tag;
totlen = tag = 0;
stream_get_mark(s, bm);
/* sequence tag */
if(((len = krb_decode_sequence_tag(s, &verlen)) == 0) || (verlen != (maxlen - len)))
goto err;
totlen += len;
/* version no[0] */
if(((len = krb_decode_int(s, tag++, (uint32*)&(krb_err->pvno))) == 0))
goto err;
totlen += len;
verlen -= len;
/* msg type[1] */
if((verlen <= 0) || ((len = krb_decode_int(s, tag++, (uint32*)&(krb_err->type))) == 0))
goto err;
totlen += len;
verlen -= len;
/* skip tag 2 3 */
for(i = 2;i < 4;i++)
{
if(verlen <= 0)
goto err;
len = krb_skip_contextual_tag(s, tag++);
verlen -= len;
totlen += len;
}
/* stime[4] */
if((verlen <= 0) || ((len = krb_decode_time(s, tag++, &(krb_err->stime))) == 0))
goto err;
totlen += len;
verlen -= len;
/* skip tag 5 */
if(verlen <= 0)
goto err;
len = krb_skip_contextual_tag(s, tag++);
totlen += len;
verlen -= len;
/* error code[6] */
if((verlen <= 0) || ((len = krb_decode_int(s, tag++, (uint32*)&(krb_err->errcode))) == 0))
goto err;
totlen += len;
verlen -= len;
/* skip tag 7, 8, 9, 10, 11 */
for(i = 7;i < 12;i++)
{
if(verlen <= 0)
goto err;
else if(verlen == 0)
return totlen;
len = krb_skip_contextual_tag(s, tag++);
verlen -= len;
totlen += len;
}
/* edata (tag 12) */
if((verlen < 0) || ((len = krb_decode_octet_string(s, tag++, (uint8**)&(krb_err->edata.data), &(krb_err->edata.length))) == 0))
goto err;
totlen += len;
if(verlen != len)
goto err;
return totlen;
err:
krb_free_krb_error(krb_err);
return 0;
}
ENCKDCREPPart* krb_decode_enc_reppart(rdpBlob* msg, uint8 apptag)
{
int len, tmp, verlen;
STREAM* s;
char* timestr;
ENCKDCREPPart* reppart;
reppart = xnew(ENCKDCREPPart);
s = stream_new(0);
stream_attach(s, msg->data + 24, msg->length);
verlen = msg->length - 24;
/* application tag */
if((verlen <= 0) || ((len = krb_decode_application_tag(s, apptag, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
verlen -= len;
/* sequence tag */
if((verlen <= 0) || ((len = krb_decode_sequence_tag(s, &tmp)) == 0) || (tmp != (verlen - len)))
goto err;
verlen -= len;
/* skey[0] */
if((verlen <= 0) || ((len = krb_decode_contextual_tag(s, 0, &tmp)) == 0))
goto err;
verlen -= len;
if((verlen <= 0) || ((len = krb_decode_enckey(s, &(reppart->key))) == 0))
goto err;
verlen -= len;
/* skip tag 1 (last req) */
if(verlen <= 0)
goto err;
len = krb_skip_contextual_tag(s, 1);
verlen -= len;
/* nonce[2] */
if((verlen <= 0) || ((len = krb_decode_int(s, 2, (uint32*)&(reppart->nonce))) == 0))
goto err;
verlen -= len;
/* skip tag 3 (key expiration) */
if(verlen <= 0)
goto err;
len = krb_skip_contextual_tag(s, 3);
verlen -= len;
/* TicketFlags[4] */
if((verlen <= 0) || ((len = krb_decode_flags(s, 4, (uint32*)&(reppart->flags))) == 0))
goto err;
verlen -= len;
/* authtime[5] */
if((verlen <= 0) || ((len = krb_decode_time(s, 5, &timestr)) == 0))
goto err;
reppart->authtime = get_local_time(timestr);
verlen -= len;
xfree(timestr);
/* skip tag 6 (start time) */
if(verlen <= 0)
goto err;
len = krb_skip_contextual_tag(s, 6);
verlen -= len;
/* endtime[7] */
if((verlen <= 0) || ((len = krb_decode_time(s, 7, &timestr)) == 0))
goto err;
reppart->endtime = get_local_time(timestr);
verlen -= len;
xfree(timestr);
/* skip tag 8 (renew till) */
if(verlen <= 0)
goto err;
len = krb_skip_contextual_tag(s, 8);
verlen -= len;
/* realm[9] */
if((verlen <= 0) || ((len = krb_decode_string(s, 9, &(reppart->realm))) == 0))
goto err;
verlen -= len;
/* sname[10] */
if((verlen <= 0) || ((len = krb_decode_sname(s, 10, &(reppart->sname))) == 0))
goto err;
verlen -= len;
/* skip tag 11, 12 (tag 12 is supported enctypes) */
if(verlen <= 0)
goto err;
len = krb_skip_contextual_tag(s, 11);
len += krb_skip_contextual_tag(s, 12);
verlen -= len;
if(verlen != 0)
goto err;
stream_detach(s);
return reppart;
err:
krb_free_reppart(reppart);
xfree(reppart);
return NULL;
}
int krb_decode_tgtrep(STREAM* s, KrbTGTREP* krb_tgtrep)
{
uint8* bm;
int totlen, len, verlen;
totlen = 0;
stream_get_mark(s, bm);
/* sequence tag */
if(((len = krb_decode_sequence_tag(s, &verlen)) == 0))
goto err;
totlen += len;
/* version no[0] */
if(((len = krb_decode_int(s, 0, (uint32*)&(krb_tgtrep->pvno))) == 0))
goto err;
totlen += len;
verlen -= len;
/* msg type[1] */
if((verlen <= 0) || ((len = krb_decode_int(s, 1, (uint32*)&(krb_tgtrep->type))) == 0))
goto err;
totlen += len;
verlen -= len;
/* ticket[2] */
if((verlen <= 0) || ((len = krb_decode_ticket(s, 2, &(krb_tgtrep->ticket))) == 0))
goto err;
totlen += len;
if(verlen != len)
goto err;
return totlen;
err:
stream_set_mark(s, bm);
return 0;
}

View File

@ -0,0 +1,47 @@
/**
* FreeRDP: A Remote Desktop Protocol Client
* Kerberos Auth Protocol DER Decode
*
* 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 <freerdp/crypto/der.h>
#include "kerberos.h"
#ifndef __KRB_DECODE_H
#define __KRB_DECODE_H
int krb_decode_application_tag(STREAM* s, uint8 tag, int *length);
int krb_decode_sequence_tag(STREAM* s, int *length);
int krb_skip_contextual_tag(STREAM* s, uint8 tag);
int krb_decode_contextual_tag(STREAM* s, uint8 tag, int *length);
int krb_decode_integer(STREAM* s, uint32* value);
int krb_decode_time(STREAM* s, uint8 tag, char** str);
int krb_decode_int(STREAM* s, uint8 tag, uint32* result);
int krb_decode_flags(STREAM* s, uint8 tag, uint32* flags);
int krb_decode_string(STREAM* s, uint8 tag, char** str);
int krb_decode_octet_string(STREAM* s, uint8 tag, uint8** data, int* length);
int krb_decode_cname(STREAM* s, uint8 tag, char** str);
int krb_decode_sname(STREAM* s, uint8 tag, char** str);
int krb_decode_enckey(STREAM* s, KrbENCKey* key);
int krb_decode_encrypted_data(STREAM* s, KrbENCData* enc_data);
int krb_decode_ticket(STREAM* s, uint8 tag, Ticket* ticket);
int krb_decode_kdc_rep(STREAM* s, KrbKDCREP* kdc_rep, sint32 maxlen);
int krb_decode_krb_error(STREAM* s, KrbERROR* krb_err, sint32 maxlen);
ENCKDCREPPart* krb_decode_enc_reppart(rdpBlob* msg, uint8 apptag);
int krb_decode_tgtrep(STREAM* s, KrbTGTREP* krb_tgtrep);
#endif /* __KRB_DECODE_H */

View File

@ -0,0 +1,389 @@
/**
* 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;
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, (char*[]){ cname, NULL });
stream_set_mark(s, bm);
return len;
}
int krb_encode_sname(STREAM* s, uint8 tag, char* sname)
{
uint8* bm;
char* str;
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 = index(sname, '/') - sname;
str = (char*)xzalloc(tmp + 1);
strncpy(str, sname, tmp);
der_write_principal_name(s, NAME_TYPE_SERVICE, (char*[]){ str, (sname + tmp + 1), NULL });
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, curlen;
totlen = 0;
PAData** lpa_data;
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;
}

View File

@ -0,0 +1,48 @@
/**
* 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 <freerdp/crypto/der.h>
#include "kerberos.h"
#ifndef __KRB_ENCODE_H
#define __KRB_ENCODE_H
int krb_encode_sequence_tag(STREAM* s, uint32 len);
int krb_encode_contextual_tag(STREAM* s, uint8 tag, uint32 len);
int krb_encode_application_tag(STREAM* s, uint8 tag, uint32 len);
int krb_encode_recordmark(STREAM* s, uint32 len);
int krb_encode_cname(STREAM* s, uint8 tag, char* cname);
int krb_encode_sname(STREAM* s, uint8 tag, char* sname);
int krb_encode_uint8(STREAM* s, uint8 tag, uint8 val);
int krb_encode_integer(STREAM* s, uint8 tag, int val);
int krb_encode_options(STREAM* s, uint8 tag, uint32 options);
int krb_encode_string(STREAM* s, uint8 tag, char* str);
int krb_encode_time(STREAM* s, uint8 tag, char* strtime);
int krb_encode_octet_string(STREAM* s, uint8* string, uint32 len);
int krb_encode_padata(STREAM* s, PAData** pa_data);
int krb_encode_encrypted_data(STREAM* s, KrbENCData* enc_data);
int krb_encode_checksum(STREAM* s, rdpBlob* cksum, int cktype);
int krb_encode_authenticator(STREAM* s, Authenticator *krb_auth);
int krb_encode_ticket(STREAM* s, uint8 tag, Ticket* ticket);
int krb_encode_req_body(STREAM* s, KDCReqBody* req_body, int msgtype);
int krb_encode_apreq(STREAM* s, KrbAPREQ* krb_apreq);
int krb_encode_tgtreq(STREAM* s, KrbTGTREQ* krb_tgtreq);
#endif /* __KRB_ENCODE_H */

View File

@ -45,3 +45,9 @@ void freerdp_blob_free(rdpBlob* blob)
blob->length = 0; blob->length = 0;
} }
void freerdp_blob_copy(rdpBlob* dstblob, rdpBlob* srcblob)
{
freerdp_blob_alloc(dstblob, srcblob->length);
memcpy(dstblob->data, srcblob->data, dstblob->length);
}

View File

@ -125,3 +125,23 @@ char* xstrdup(const char* str)
return mem; return mem;
} }
char* xstrtoup(const char* str)
{
char* out;
char* p;
int c;
out = xstrdup(str);
if(out != NULL)
{
p = out;
while(*p != '\0')
{
c = toupper((unsigned char)*p);
*p++ = (char)c;
}
return out;
}
else
return NULL;
}