Example #1
0
void settings_free(rdpSettings* settings)
{
	if (settings != NULL)
	{
		freerdp_uniconv_free(settings->uniconv);
		xfree(settings->hostname);
		xfree(settings->username);
		xfree(settings->password);
		xfree(settings->domain);
		xfree(settings->shell);
		xfree(settings->directory);
		xfree(settings->ip_address);
		xfree(settings->client_dir);
		xfree(settings->cert_file);
		xfree(settings->privatekey_file);
		freerdp_blob_free(settings->server_random);
		freerdp_blob_free(settings->server_certificate);
		xfree(settings->server_random);
		xfree(settings->server_certificate);
		xfree(settings->rdp_key_file);
		certificate_free(settings->server_cert);
		xfree(settings->client_auto_reconnect_cookie);
		xfree(settings->server_auto_reconnect_cookie);
		xfree(settings->client_time_zone);
		xfree(settings->bitmapCacheV2CellInfo);
		xfree(settings->glyphCache);
		xfree(settings->fragCache);
		key_free(settings->server_key);
		xfree(settings->config_path);
		xfree(settings->current_path);
		xfree(settings->development_path);
		xfree(settings);
	}
}
Example #2
0
int credssp_authenticate(rdpCredssp* credssp)
{
	NTLMSSP* ntlmssp = credssp->ntlmssp;
	STREAM* s = stream_new(0);
	uint8* negoTokenBuffer = (uint8*) xmalloc(2048);

	if (credssp_ntlmssp_init(credssp) == 0)
		return 0;

	if (credssp_get_public_key(credssp) == 0)
		return 0;

	/* NTLMSSP NEGOTIATE MESSAGE */
	s->p = s->data = negoTokenBuffer;
	ntlmssp_send(ntlmssp, s);
	credssp->negoToken.data = s->data;
	credssp->negoToken.length = s->p - s->data;
	credssp_send(credssp, &credssp->negoToken, NULL, NULL);

	/* NTLMSSP CHALLENGE MESSAGE */
	if (credssp_recv(credssp, &credssp->negoToken, NULL, NULL) < 0)
		return -1;

	s->p = s->data = credssp->negoToken.data;
	ntlmssp_recv(ntlmssp, s);

	freerdp_blob_free(&credssp->negoToken);

	/* NTLMSSP AUTHENTICATE MESSAGE */
	s->p = s->data = negoTokenBuffer;
	ntlmssp_send(ntlmssp, s);

	/* The last NTLMSSP message is sent with the encrypted public key */
	credssp->negoToken.data = s->data;
	credssp->negoToken.length = s->p - s->data;
	credssp_encrypt_public_key(credssp, &credssp->pubKeyAuth);
	credssp_send(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth);

	/* Encrypted Public Key +1 */
	if (credssp_recv(credssp, &credssp->negoToken, NULL, &credssp->pubKeyAuth) < 0)
		return -1;

	if (credssp_verify_public_key(credssp, &credssp->pubKeyAuth) == 0)
	{
		/* Failed to verify server public key echo */
		return 0; /* DO NOT SEND CREDENTIALS! */
	}

	freerdp_blob_free(&credssp->negoToken);
	freerdp_blob_free(&credssp->pubKeyAuth);

	/* Send encrypted credentials */
	credssp_encode_ts_credentials(credssp);
	credssp_encrypt_ts_credentials(credssp, &credssp->authInfo);
	credssp_send(credssp, NULL, &credssp->authInfo, NULL);

	xfree(s);

	return 1;
}
Example #3
0
void redirection_free(rdpRedirection* redirection)
{
	if (redirection != NULL)
	{
		//these four have already been freed in settings_free() and freerdp_string_free() checks for NULL
		redirection->username.ascii = NULL;
		redirection->domain.ascii = NULL;
		redirection->targetNetAddress.ascii = NULL;
		redirection->targetNetBiosName.ascii = NULL;

		freerdp_string_free(&redirection->tsvUrl);
		freerdp_string_free(&redirection->username);
		freerdp_string_free(&redirection->domain);
		freerdp_blob_free(&redirection->password_cookie);
		freerdp_string_free(&redirection->targetFQDN);
		freerdp_string_free(&redirection->targetNetBiosName);
		freerdp_string_free(&redirection->targetNetAddress);
		freerdp_blob_free(&redirection->loadBalanceInfo);

		if (redirection->targetNetAddresses != NULL)
		{
			int i;

			for (i = 0; i < (int) redirection->targetNetAddressesCount; i++)
				freerdp_string_free(&redirection->targetNetAddresses[i]);

			xfree(redirection->targetNetAddresses);
		}

		xfree(redirection);
	}
}
Example #4
0
void kerberos_ContextFree(KRB_CONTEXT* krb_ctx)
{
	if (krb_ctx != NULL)
	{
		xfree(krb_ctx->krbhost);
		xfree(krb_ctx->cname);
		xfree(krb_ctx->realm);
		freerdp_blob_free(&(krb_ctx->passwd));

		if(krb_ctx->askey != NULL)
		{
			freerdp_blob_free(&(krb_ctx->askey->skey));
			xfree(krb_ctx->askey);
		}
		
		if(krb_ctx->tgskey != NULL)
		{
			freerdp_blob_free(&(krb_ctx->tgskey->skey));
			xfree(krb_ctx->tgskey);
		}

		krb_free_ticket(&(krb_ctx->asticket));
		krb_free_ticket(&(krb_ctx->tgsticket));
		krb_ctx->state = KRB_STATE_FINAL;
	}
}
Example #5
0
void key_free(rdpKey* key)
{
	if (key != NULL)
	{
		freerdp_blob_free(&key->modulus);
		freerdp_blob_free(&key->private_exponent);
		xfree(key);
	}
}
Example #6
0
void credssp_free(rdpCredssp* credssp)
{
	if (credssp != NULL)
	{
		freerdp_blob_free(&credssp->public_key);
		freerdp_blob_free(&credssp->ts_credentials);

		ntlmssp_free(credssp->ntlmssp);
		xfree(credssp);
	}
}
Example #7
0
int credssp_verify_public_key(rdpCredssp* credssp, rdpBlob* d)
{
	uint8 *p1, *p2;
	uint8 *signature;
	rdpBlob public_key;
	rdpBlob encrypted_public_key;

	signature = d->data;
	encrypted_public_key.data = (void*) (signature + 16);
	encrypted_public_key.length = d->length - 16;

	ntlmssp_decrypt_message(credssp->ntlmssp, &encrypted_public_key, &public_key, signature);

	p1 = (uint8*) credssp->public_key.data;
	p2 = (uint8*) public_key.data;

	p2[0]--;

	if (memcmp(p1, p2, public_key.length) != 0)
	{
		printf("Could not verify server's public key echo\n");
		return 0;
	}

	p2[0]++;
	freerdp_blob_free(&public_key);
	return 1;
}
Example #8
0
void credssp_encrypt_public_key(rdpCredssp* credssp, rdpBlob* d)
{
	uint8 *p;
	uint8 signature[16];
	rdpBlob encrypted_public_key;
	NTLMSSP *ntlmssp = credssp->ntlmssp;

	freerdp_blob_alloc(d, credssp->public_key.length + 16);
	ntlmssp_encrypt_message(ntlmssp, &credssp->public_key, &encrypted_public_key, signature);

#ifdef WITH_DEBUG_NLA
	printf("Public Key (length = %d)\n", credssp->public_key.length);
	freerdp_hexdump(credssp->public_key.data, credssp->public_key.length);
	printf("\n");

	printf("Encrypted Public Key (length = %d)\n", encrypted_public_key.length);
	freerdp_hexdump(encrypted_public_key.data, encrypted_public_key.length);
	printf("\n");

	printf("Signature\n");
	freerdp_hexdump(signature, 16);
	printf("\n");
#endif

	p = (uint8*) d->data;
	memcpy(p, signature, 16); /* Message Signature */
	memcpy(&p[16], encrypted_public_key.data, encrypted_public_key.length); /* Encrypted Public Key */

	freerdp_blob_free(&encrypted_public_key);
}
Example #9
0
void credssp_encrypt_ts_credentials(rdpCredssp* credssp, rdpBlob* d)
{
	uint8 *p;
	uint8 signature[16];
	rdpBlob encrypted_ts_credentials;
	NTLMSSP *ntlmssp = credssp->ntlmssp;

	freerdp_blob_alloc(d, credssp->ts_credentials.length + 16);
	ntlmssp_encrypt_message(ntlmssp, &credssp->ts_credentials, &encrypted_ts_credentials, signature);

#ifdef WITH_DEBUG_NLA
	printf("TSCredentials (length = %d)\n", credssp->ts_credentials.length);
	freerdp_hexdump(credssp->ts_credentials.data, credssp->ts_credentials.length);
	printf("\n");

	printf("Encrypted TSCredentials (length = %d)\n", encrypted_ts_credentials.length);
	freerdp_hexdump(encrypted_ts_credentials.data, encrypted_ts_credentials.length);
	printf("\n");

	printf("Signature\n");
	freerdp_hexdump(signature, 16);
	printf("\n");
#endif

	p = (uint8*) d->data;
	memcpy(p, signature, 16); /* Message Signature */
	memcpy(&p[16], encrypted_ts_credentials.data, encrypted_ts_credentials.length); /* Encrypted TSCredentials */

	freerdp_blob_free(&encrypted_ts_credentials);
}
Example #10
0
void redirection_free(rdpRedirection* redirection)
{
	if (redirection != NULL)
	{
		freerdp_string_free(&redirection->tsvUrl);
		freerdp_string_free(&redirection->username);
		freerdp_string_free(&redirection->domain);
		freerdp_string_free(&redirection->password);
		freerdp_string_free(&redirection->targetFQDN);
		freerdp_string_free(&redirection->targetNetBiosName);
		freerdp_string_free(&redirection->targetNetAddress);
		freerdp_blob_free(&redirection->loadBalanceInfo);

		if (redirection->targetNetAddresses != NULL)
		{
			int i;

			for (i = 0; i < redirection->targetNetAddressesCount; i++)
				freerdp_string_free(&redirection->targetNetAddresses[i]);

			xfree(redirection->targetNetAddresses);
		}

		xfree(redirection);
	}
}
Example #11
0
void krb_free_krb_error(KrbERROR* krb_err)
{
	if(krb_err != NULL)
	{
		xfree(krb_err->stime);
		freerdp_blob_free(&(krb_err->edata));
	}
}
Example #12
0
void krb_free_reppart(ENCKDCREPPart* reppart)
{
	if(reppart != NULL)
	{
		freerdp_blob_free(&(reppart->key.skey));
		xfree(reppart->sname);
		xfree(reppart->realm);
	}
}
Example #13
0
void krb_free_ticket(Ticket* ticket)
{
	if (ticket != NULL)
	{
		xfree(ticket->realm);
		xfree(ticket->sname);
		freerdp_blob_free(&(ticket->enc_part.encblob));
		ticket->enc_part.encblob.data = NULL;
	}
}
Example #14
0
void krb_free_kdcrep(KrbKDCREP* kdc_rep)
{
	if(kdc_rep != NULL)
	{
		krb_free_padata(kdc_rep->padata);
		xfree(kdc_rep->cname);
		xfree(kdc_rep->realm);
		krb_free_ticket(&(kdc_rep->etgt));
		freerdp_blob_free(&(kdc_rep->enc_part.encblob));
		kdc_rep->enc_part.encblob.data = NULL;
	}
}
Example #15
0
void certificate_free(rdpCertificate* certificate)
{
	if (certificate != NULL)
	{
		certificate_free_x509_certificate_chain(certificate->x509_cert_chain);

		if (certificate->cert_info.modulus.data != NULL)
			freerdp_blob_free(&(certificate->cert_info.modulus));

		xfree(certificate);
	}
}
Example #16
0
void tls_free(rdpTls* tls)
{
	if (tls != NULL)
	{
		if (tls->ssl)
			SSL_free(tls->ssl);

		if (tls->ctx)
			SSL_CTX_free(tls->ctx);

		freerdp_blob_free(&tls->public_key);

		certificate_store_free(tls->certificate_store);

		xfree(tls);
	}
}
Example #17
0
boolean certificate_read_server_x509_certificate_chain(rdpCertificate* certificate, STREAM* s)
{
	int i;
	uint32 certLength;
	uint32 numCertBlobs;

	DEBUG_CERTIFICATE("Server X.509 Certificate Chain");

	stream_read_uint32(s, numCertBlobs); /* numCertBlobs */

	certificate->x509_cert_chain = certificate_new_x509_certificate_chain(numCertBlobs);

	for (i = 0; i < (int) numCertBlobs; i++)
	{
		stream_read_uint32(s, certLength);

		DEBUG_CERTIFICATE("\nX.509 Certificate #%d, length:%d", i + 1, certLength);

		certificate->x509_cert_chain->array[i].data = (uint8*) xmalloc(certLength);
		stream_read(s, certificate->x509_cert_chain->array[i].data, certLength);
		certificate->x509_cert_chain->array[i].length = certLength;

		if (numCertBlobs - i == 2)
		{
			rdpCertInfo cert_info;
			DEBUG_CERTIFICATE("License Server Certificate");
			certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &cert_info);
			DEBUG_LICENSE("modulus length:%d", cert_info.modulus.length);
			freerdp_blob_free(&cert_info.modulus);
		}
		else if (numCertBlobs - i == 1)
		{
			DEBUG_CERTIFICATE("Terminal Server Certificate");
			certificate_read_x509_certificate(&certificate->x509_cert_chain->array[i], &certificate->cert_info);
			DEBUG_CERTIFICATE("modulus length:%d", certificate->cert_info.modulus.length);
		}
	}

	return true;
}
Example #18
0
boolean rdp_client_redirect(rdpRdp* rdp)
{
	rdpSettings* settings = rdp->settings;
	rdpRedirection* redirection = rdp->redirection;

	rdp_client_disconnect(rdp);

	/* FIXME: this is a subset of rdp_free */
	crypto_rc4_free(rdp->rc4_decrypt_key);
	crypto_rc4_free(rdp->rc4_encrypt_key);
	crypto_des3_free(rdp->fips_encrypt);
	crypto_des3_free(rdp->fips_decrypt);
	crypto_hmac_free(rdp->fips_hmac);
	mcs_free(rdp->mcs);
	nego_free(rdp->nego);
	license_free(rdp->license);
	transport_free(rdp->transport);

	/* FIXME: this is a subset of settings_free */
	freerdp_blob_free(settings->server_random);
	freerdp_blob_free(settings->server_certificate);
	xfree(settings->ip_address);

	rdp->transport = transport_new(settings);
	rdp->license = license_new(rdp);
	rdp->nego = nego_new(rdp->transport);
	rdp->mcs = mcs_new(rdp->transport);

	rdp->transport->layer = TRANSPORT_LAYER_TCP;
	settings->redirected_session_id = redirection->sessionID;

	if (redirection->flags & LB_LOAD_BALANCE_INFO)
	{
		nego_set_routing_token(rdp->nego, &redirection->loadBalanceInfo);
	}
	else
	{
		if (redirection->flags & LB_TARGET_NET_ADDRESS)
		{
			xfree(settings->hostname);
			settings->hostname = xstrdup(redirection->targetNetAddress.ascii);
		}
		else if (redirection->flags & LB_TARGET_FQDN)
		{
			xfree(settings->hostname);
			settings->hostname = xstrdup(redirection->targetFQDN.ascii);
		}
		else if (redirection->flags & LB_TARGET_NETBIOS_NAME)
		{
			xfree(settings->hostname);
			settings->hostname = xstrdup(redirection->targetNetBiosName.ascii);
		}
	}

	if (redirection->flags & LB_USERNAME)
	{
		xfree(settings->username);
		settings->username = xstrdup(redirection->username.ascii);
	}

	if (redirection->flags & LB_DOMAIN)
	{
		xfree(settings->domain);
		settings->domain = xstrdup(redirection->domain.ascii);
	}

	if (redirection->flags & LB_PASSWORD)
	{
		settings->password_cookie = &redirection->password_cookie;
	}

	return rdp_client_connect(rdp);
}
Example #19
0
int krb_verify_kdcrep(KRB_CONTEXT* krb_ctx, KrbKDCREP* kdc_rep, int msgtype)
{
	ENCKDCREPPart* reppart;
	KrbENCKey* key;
	rdpBlob* decmsg;
	uint8 tag;
	tag = 0;
	key = NULL;

	/* Verify everything */
	if((kdc_rep->pvno != KRB_VERSION) || (kdc_rep->type != msgtype) || strcasecmp(kdc_rep->cname, krb_ctx->cname) || strcasecmp(kdc_rep->realm, krb_ctx->realm))
	{
		krb_ctx->state = KRB_PACKET_ERROR;
		return -1;
	}
	/* decrypt enc-part */
	decmsg = xnew(rdpBlob);
	if(krb_ctx->askey->enctype != kdc_rep->enc_part.enctype && msgtype == KRB_TAG_ASREP)
	{
		freerdp_blob_free(&(krb_ctx->askey->skey));
		xfree(krb_ctx->askey);
		krb_ctx->askey = string2key(&(krb_ctx->passwd), kdc_rep->enc_part.enctype);
	}
	krb_ctx->askey->enctype = kdc_rep->enc_part.enctype;
	decmsg = crypto_kdcmsg_decrypt(&(kdc_rep->enc_part.encblob), krb_ctx->askey, 8); //RFC4757 section 3 for msgtype (T=8)

	if(msgtype == KRB_TAG_ASREP)
	{
		key = krb_ctx->askey;
		tag = 25;
	}
	else if (msgtype == KRB_TAG_TGSREP)
	{
		key = krb_ctx->tgskey;
		tag = 26;
	}

	/* KDC-REP-PART decode */
	if(decmsg == NULL || ((reppart = krb_decode_enc_reppart(decmsg, tag)) == NULL))
	{
		krb_ctx->state = KRB_PACKET_ERROR;
		return -1;
	}
	freerdp_blob_free(decmsg);
	xfree(decmsg);

	/* Verify KDC-REP-PART */
	if(reppart->nonce != krb_ctx->nonce || strcasecmp(reppart->realm, krb_ctx->realm) || strcasecmp(reppart->sname, krb_ctx->sname))
	{
		krb_free_reppart(reppart);
		xfree(reppart);
		krb_ctx->state = KRB_PACKET_ERROR;
		return -1;
	}

	/* save stuff */
	krb_ctx->clockskew = reppart->authtime - krb_ctx->ctime; //Used to synchronize clocks 
	krb_save_ticket(krb_ctx, kdc_rep);
	freerdp_blob_copy(&(key->skey), &(reppart->key.skey));
	key->enctype = reppart->key.enctype;
	krb_free_reppart(reppart);
	xfree(reppart);
	return 0;
}
Example #20
0
void krb_tgsreq_send(KRB_CONTEXT* krb_ctx, uint8 errcode)
{
	KrbTGSREQ* krb_tgsreq;
	KrbAPREQ* krb_apreq;
	PAData** pa_data;
	Authenticator* krb_auth;
	STREAM* s;
	STREAM* sapreq;
	rdpBlob msg;
	uint32 curlen, totlen, tmp;
	uint8 *bm;
	bm = NULL;
	totlen = tmp = 0;
	krb_tgsreq = krb_tgsreq_new(krb_ctx, errcode);
	krb_auth = xnew(Authenticator);
	pa_data = krb_tgsreq->padata;
	s = stream_new(4096);
	sapreq = stream_new(2048);
	
	//Begin write asn1 data reversely into stream
	stream_seek(s, 4095);
	stream_seek(sapreq, 2047);
	
	/* KDC-REQ-BODY (TAG 4) */
	totlen += krb_encode_req_body(s, &(krb_tgsreq->req_body), krb_tgsreq->type);
	stream_get_mark(s, bm);
	tmp = totlen;
	totlen += krb_encode_contextual_tag(s, 4, totlen);

	msg.data = bm;
	msg.length = tmp;

	/* Authenticator */
	krb_auth->avno = KRB_VERSION;
	krb_auth->cname = krb_ctx->cname;
	krb_auth->crealm = krb_ctx->realm;
	krb_auth->cksumtype = get_cksum_type(krb_ctx->enctype);
	krb_auth->cksum = crypto_kdcmsg_cksum(&msg, krb_ctx->askey, 6); //RFC4757 section 3 for msgtype (T=6)
	krb_auth->ctime = krb_tgsreq->req_body.from;
	krb_auth->cusec = 0;
	crypto_nonce((uint8*)&(krb_auth->seqno), 4);

	/* PA-TGS-REQ */
	krb_apreq = krb_apreq_new(krb_ctx, &(krb_ctx->asticket), krb_auth);
	curlen = krb_encode_apreq(sapreq, krb_apreq);
	msg.data = sapreq->p;
	msg.length = curlen;
	(*pa_data)->type = 1;
	(*pa_data)->value = msg;

	/* PA-DATA (TAG 3) */
	curlen = krb_encode_padata(s, pa_data);
	totlen += curlen + krb_encode_contextual_tag(s, 3, curlen);

	/* MSGTYPE (TAG 2) */
	totlen += krb_encode_uint8(s, 2, krb_tgsreq->type);

	/* VERSION NO (TAG 1) */
	totlen += krb_encode_uint8(s, 1, krb_tgsreq->pvno);

	totlen += krb_encode_sequence_tag(s, totlen);
	totlen += krb_encode_application_tag(s, krb_tgsreq->type, totlen);
	totlen += krb_encode_recordmark(s, totlen);

	/* READY SEND */
	krb_tcp_send(krb_ctx, s->p, totlen);
	
	/* save stuff */
	krb_ctx->nonce = krb_tgsreq->req_body.nonce;
	xfree(krb_ctx->sname);
	krb_ctx->sname = xstrdup(krb_tgsreq->req_body.sname);
	krb_ctx->ctime = get_local_time(krb_tgsreq->req_body.from);
	krb_ctx->state = KRB_TGSREQ_OK;

	/* clean up */
	freerdp_blob_free(krb_auth->cksum);
	xfree(krb_auth->cksum);
	xfree(krb_auth);
	krb_free_tgsreq(krb_tgsreq);
	xfree(krb_tgsreq);
	stream_free(sapreq);
	stream_free(s);
}
Example #21
0
void krb_asreq_send(KRB_CONTEXT* krb_ctx, uint8 errcode)
{
	KrbASREQ* krb_asreq;
	PAData** pa_data;
	KrbENCData enc_data;
	KrbENCKey* enckey;
	STREAM* s;
	STREAM* paenc;
	rdpBlob msg;
	rdpBlob* encmsg;
	uint32 curlen, totlen, pai;
	uint8 *bm;
	bm = NULL;
	totlen = pai = 0;
	krb_asreq = krb_asreq_new(krb_ctx, errcode);
	pa_data = krb_asreq->padata;
	enckey = NULL;
	s = stream_new(2048);
	paenc = stream_new(100);
	
	//Begin write asn1 data reversely into stream
	stream_seek(s, 1024);
	stream_seek(paenc, 99);
	
	/* KDC-REQ-BODY (TAG 4) */
	totlen += krb_encode_req_body(s, &(krb_asreq->req_body), krb_asreq->type);
	totlen += krb_encode_contextual_tag(s, 4, totlen);

	/* padata = PA-ENC-TIMESTAMP */
	if(errcode != 0)
	{
		freerdp_blob_alloc(&msg, 21);
		memcpy(msg.data, "\x30\x13\xa0\x11\x18\x0f", 6); // PA-ENC-TS-ENC without optional pausec
		memcpy(((uint8*) msg.data) + 6, krb_asreq->req_body.from, 15);
		enckey = string2key(&(krb_ctx->passwd), krb_ctx->enctype);
		encmsg = crypto_kdcmsg_encrypt(&msg, enckey, 1); //RFC4757 section 3 for msgtype (T=1)
		enc_data.enctype = enckey->enctype;
		enc_data.kvno = -1;
		enc_data.encblob.data = encmsg->data;
		enc_data.encblob.length = encmsg->length;
		curlen = krb_encode_encrypted_data(paenc, &enc_data);
		freerdp_blob_free(&msg);
		msg.data = paenc->p;
		msg.length = curlen;

		/* padata = PA-ENC-TIMESTAMP */
		(*(pa_data + pai))->type = 2;
		(*(pa_data + pai))->value = msg;
		pai++;
		freerdp_blob_free(encmsg);
		xfree(encmsg);
	}
	
	freerdp_blob_alloc(&msg, 7);
	memcpy(msg.data, "\x30\x05\xa0\03\x01\x01", 6); // asn1 data
	*((uint8*)msg.data + 6) = krb_asreq->pa_pac_request;

	/* padata = PA-PAC-REQUEST */
	(*(pa_data + pai))->type = 128;
	(*(pa_data + pai))->value = msg;

	*(pa_data + ++pai) = NULL;

	/* padata (TAG 3) */
	curlen = krb_encode_padata(s, pa_data);
	totlen += curlen + krb_encode_contextual_tag(s, 3, curlen);

	/* MSGTYPE = AS-REQ (TAG 2) */
	totlen += krb_encode_uint8(s, 2, krb_asreq->type);

	/* KERBEROS PROTOCOL VERSION NO (TAG 1)*/
	totlen += krb_encode_uint8(s, 1, krb_asreq->pvno);

	totlen += krb_encode_sequence_tag(s, totlen);
	totlen += krb_encode_application_tag(s, krb_asreq->type, totlen);
	totlen += krb_encode_recordmark(s, totlen);

	/* READY SEND */
	krb_tcp_send(krb_ctx, s->p, totlen);

	/* save stuff */
	krb_ctx->askey = enckey;
	krb_ctx->nonce = krb_asreq->req_body.nonce;
	xfree(krb_ctx->sname);
	krb_ctx->sname = xstrdup(krb_asreq->req_body.sname);
	krb_ctx->ctime = get_local_time(krb_asreq->req_body.from);
	krb_ctx->state = KRB_ASREQ_OK;

	/* clean up */
	freerdp_blob_free(&msg);
	stream_free(s);
	stream_free(paenc);
	krb_free_asreq(krb_asreq);
	xfree(krb_asreq);
}