Index: cssp.c =================================================================== --- cssp.c (revision 1696) +++ cssp.c (working copy) @@ -1,7 +1,7 @@ /* -*- c-basic-offset: 8 -*- rdesktop: A Remote Desktop Protocol client. CredSSP layer and kerberos support. - Copyright 2012 Henrik Andersson for Cendio AB + Copyright 2012-2013 Henrik Andersson for Cendio AB This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,6 +20,8 @@ #include #include "rdesktop.h" +extern RD_BOOL g_use_password_as_pin; + static gss_OID_desc _gss_spnego_krb5_mechanism_oid_desc = { 9, (void *) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" }; @@ -285,6 +287,173 @@ return out; } +/* KeySpecs from wincrypt.h */ +#define AT_KEYEXCHANGE 1 +#define AT_SIGNATURE 2 + +static STREAM +cssp_encode_tscspdatadetail(int keyspec, char *card, char *reader, char *container, char *csp) +{ + int i; + STREAM out; + STREAM h1, h2; + struct stream tmp = { 0 }; + struct stream message = { 0 }; + + // allocate local streams + tmp.size = 4096; + tmp.data = xmalloc(tmp.size); + s_reset(&tmp); + + message.size = 4096; + message.data = xmalloc(message.size); + s_reset(&message); + + unsigned char serial[] = {AT_SIGNATURE & AT_KEYEXCHANGE}; + +#if 0 + unsigned char serial[] = { + 0x00,0xFA, 0x9B, 0x3F, 0x5F, 0x9F, 0x0D, 0x58, 0xDB, + 0x28, 0x13, 0xA9, 0xA4, 0xC5, 0x78, 0x34, 0xE9 + }; +#endif + + // keySpec [0] + s_reset(&tmp); + for (i = 0; i < sizeof(serial); i++) + out_uint8(&tmp, serial[i]); + s_mark_end(&tmp); + h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp); + h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); + out_uint8p(&message, h1->data, s_length(h1)); + s_free(h2); + s_free(h1); + +#if 0 + // cardName [1] + s_reset(&tmp); + for (i = 0; i < strlen(card); i++) + out_uint16_le(&tmp, card[i]); + s_mark_end(&tmp); + h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); + h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); + out_uint8p(&message, h1->data, s_length(h1)); + s_free(h2); + s_free(h1); + + // readerName [2] + s_reset(&tmp); + for (i = 0; i < strlen(reader); i++) + out_uint16_le(&tmp, reader[i]); + s_mark_end(&tmp); + h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); + h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2); + out_uint8p(&message, h1->data, s_length(h1)); + s_free(h2); + s_free(h1); + + // containerName [3] + s_reset(&tmp); + for (i = 0; i < strlen(container); i++) + out_uint16_le(&tmp, container[i]); + s_mark_end(&tmp); + h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); + h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2); + out_uint8p(&message, h1->data, s_length(h1)); + s_free(h2); + s_free(h1); + + // cspName [4] + s_reset(&tmp); + for (i = 0; i < strlen(csp); i++) + out_uint16_le(&tmp, csp[i]); + s_mark_end(&tmp); + h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); + h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 4, h2); + out_uint8p(&message, h1->data, s_length(h1)); + s_free(h2); + s_free(h1); +#endif + s_mark_end(&message); + + // build message + out = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message); + + // cleanup + free(tmp.data); + free(message.data); + return out; +} + +static STREAM +cssp_encode_tssmartcardcreds(char *username, char *password,char *domain) +{ + int i; + STREAM out, h1, h2; + struct stream tmp = { 0 }; + struct stream message = { 0 }; + + // allocate local streams + tmp.size = 4096; + tmp.data = xmalloc(tmp.size); + s_reset(&tmp); + + message.size = 4096; + message.data = xmalloc(message.size); + s_reset(&message); + + // pin [0] + s_reset(&tmp); + for (i = 0; i < strlen(password); i++) + out_uint16_le(&tmp, password[i]); + s_mark_end(&tmp); + h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); + h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); + out_uint8p(&message, h1->data, s_length(h1)); + s_free(h2); + s_free(h1); + + // cspData[1] + h2 = cssp_encode_tscspdatadetail(0x00, "", "", "identifiering", ""); + h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); + out_uint8p(&message, h1->data, s_length(h1)); + s_free(h2); + s_free(h1); + + // userHint [2] + s_reset(&tmp); + for (i = 0; i < strlen(username); i++) + out_uint16_le(&tmp, username[i]); + s_mark_end(&tmp); + h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); + h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 2, h2); + out_uint8p(&message, h1->data, s_length(h1)); + s_free(h2); + s_free(h1); + + // domainHint [3] + s_reset(&tmp); + for (i = 0; i < strlen(domain); i++) + out_uint16_le(&tmp, domain[i]); + s_mark_end(&tmp); + h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, &tmp); + h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 3, h2); + out_uint8p(&message, h1->data, s_length(h1)); + s_free(h2); + s_free(h1); + + + s_mark_end(&message); + + // build message + out = ber_wrap_hdr_data(BER_TAG_SEQUENCE | BER_TAG_CONSTRUCTED, &message); + + // cleanup + free(tmp.data); + free(message.data); + return out; +} + STREAM cssp_encode_tscredentials(char *username, char *password, char *domain) { @@ -304,7 +473,15 @@ // credType [0] s_reset(&tmp); - out_uint8(&tmp, 1); // TSPasswordCreds + if (g_use_password_as_pin == False) + { + out_uint8(&tmp, 1); // TSPasswordCreds + } + else + { + out_uint8(&tmp, 2); // TSSmartCardCreds + } + s_mark_end(&tmp); h2 = ber_wrap_hdr_data(BER_TAG_INTEGER, &tmp); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 0, h2); @@ -313,7 +490,15 @@ s_free(h1); // credentials [1] - h3 = cssp_encode_tspasswordcreds(username, password, domain); + if (g_use_password_as_pin == False) + { + h3 = cssp_encode_tspasswordcreds(username, password, domain); + } + else + { + h3 = cssp_encode_tssmartcardcreds(username, password, domain); + } + h2 = ber_wrap_hdr_data(BER_TAG_OCTET_STRING, h3); h1 = ber_wrap_hdr_data(BER_TAG_CTXT_SPECIFIC | BER_TAG_CONSTRUCTED | 1, h2); out_uint8p(&message, h1->data, s_length(h1)); Index: rdesktop.c =================================================================== --- rdesktop.c (revision 1696) +++ rdesktop.c (working copy) @@ -101,6 +101,7 @@ RD_BOOL g_owncolmap = False; RD_BOOL g_ownbackstore = True; /* We can't rely on external BackingStore */ RD_BOOL g_seamless_rdp = False; +RD_BOOL g_use_password_as_pin = False; char g_seamless_shell[512]; char g_seamless_spawn_cmd[512]; RD_BOOL g_user_quit = False; @@ -583,6 +584,7 @@ #ifdef WITH_SCARD case 'i': flags |= RDP_LOGON_PASSWORD_IS_SC_PIN; + g_use_password_as_pin = True; break; #endif case 't':