示例#1
2
文件: clispnego.c 项目: hajuuk/R7000
/*
  generate a krb5 GSS-API wrapper packet given a ticket
*/
DATA_BLOB spnego_gen_krb5_wrap(DATA_BLOB ticket, const uint8 tok_id[2])
{
	ASN1_DATA data;
	DATA_BLOB ret;

	memset(&data, 0, sizeof(data));

	asn1_push_tag(&data, ASN1_APPLICATION(0));
	asn1_write_OID(&data, OID_KERBEROS5);

	asn1_write(&data, tok_id, 2);
	asn1_write(&data, ticket.data, ticket.length);
	asn1_pop_tag(&data);

	if (data.has_error) {
		DEBUG(1,("Failed to build krb5 wrapper at offset %d\n", (int)data.ofs));
		asn1_free(&data);
	}

	ret = data_blob(data.data, data.length);
	asn1_free(&data);

	return ret;
}
示例#2
0
ssize_t read_spnego_data(DATA_BLOB data, SPNEGO_DATA *token)
{
	ASN1_DATA asn1;
	ssize_t ret = -1;

	ZERO_STRUCTP(token);
	ZERO_STRUCT(asn1);
	asn1_load(&asn1, data);

	switch (asn1.data[asn1.ofs]) {
	case ASN1_APPLICATION(0):
		asn1_start_tag(&asn1, ASN1_APPLICATION(0));
		asn1_check_OID(&asn1, OID_SPNEGO);
		if (read_negTokenInit(&asn1, &token->negTokenInit)) {
			token->type = SPNEGO_NEG_TOKEN_INIT;
		}
		asn1_end_tag(&asn1);
		break;
	case ASN1_CONTEXT(1):
		if (read_negTokenTarg(&asn1, &token->negTokenTarg)) {
			token->type = SPNEGO_NEG_TOKEN_TARG;
		}
		break;
	default:
		break;
	}

	if (!asn1.has_error) ret = asn1.ofs;
	asn1_free(&asn1);

	return ret;
}
示例#3
0
/*
  generate a krb5 GSS-API wrapper packet given a ticket
*/
DATA_BLOB spnego_gen_krb5_wrap(TALLOC_CTX *ctx, const DATA_BLOB ticket, const uint8_t tok_id[2])
{
	ASN1_DATA *data;
	DATA_BLOB ret = data_blob_null;

	data = asn1_init(talloc_tos());
	if (data == NULL) {
		return data_blob_null;
	}

	if (!asn1_push_tag(data, ASN1_APPLICATION(0))) goto err;
	if (!asn1_write_OID(data, OID_KERBEROS5)) goto err;

	if (!asn1_write(data, tok_id, 2)) goto err;
	if (!asn1_write(data, ticket.data, ticket.length)) goto err;
	if (!asn1_pop_tag(data)) goto err;

	if (!asn1_extract_blob(data, ctx, &ret)) {
		goto err;
	}

  err:

	if (asn1_has_error(data)) {
		DEBUG(1, ("Failed to build krb5 wrapper at offset %d\n",
			  (int)asn1_current_ofs(data)));
	}

	asn1_free(data);

	return ret;
}
示例#4
0
ssize_t spnego_write_data(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct spnego_data *spnego)
{
    struct asn1_data *asn1 = asn1_init(mem_ctx);
    ssize_t ret = -1;

    if (asn1 == NULL) {
        return -1;
    }

    switch (spnego->type) {
    case SPNEGO_NEG_TOKEN_INIT:
        asn1_push_tag(asn1, ASN1_APPLICATION(0));
        asn1_write_OID(asn1, GENSEC_OID_SPNEGO);
        write_negTokenInit(asn1, &spnego->negTokenInit);
        asn1_pop_tag(asn1);
        break;
    case SPNEGO_NEG_TOKEN_TARG:
        write_negTokenTarg(asn1, &spnego->negTokenTarg);
        break;
    default:
        asn1->has_error = true;
        break;
    }

    if (!asn1->has_error) {
        *blob = data_blob_talloc(mem_ctx, asn1->data, asn1->length);
        ret = asn1->ofs;
    }
    asn1_free(asn1);

    return ret;
}
示例#5
0
/*
  parse a krb5 GSS-API wrapper packet giving a ticket
*/
static bool gensec_gssapi_parse_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, DATA_BLOB *ticket, uint8_t tok_id[2])
{
    bool ret;
    struct asn1_data *data = asn1_init(mem_ctx);
    int data_remaining;

    if (!data) {
        return false;
    }

    asn1_load(data, *blob);
    asn1_start_tag(data, ASN1_APPLICATION(0));
    asn1_check_OID(data, GENSEC_OID_KERBEROS5);

    data_remaining = asn1_tag_remaining(data);

    if (data_remaining < 3) {
        data->has_error = true;
    } else {
        asn1_read(data, tok_id, 2);
        data_remaining -= 2;
        *ticket = data_blob_talloc(mem_ctx, NULL, data_remaining);
        asn1_read(data, ticket->data, ticket->length);
    }

    asn1_end_tag(data);

    ret = !data->has_error;

    asn1_free(data);

    return ret;
}
示例#6
0
ssize_t write_spnego_data(DATA_BLOB *blob, SPNEGO_DATA *spnego)
{
	ASN1_DATA asn1;
	ssize_t ret = -1;

	ZERO_STRUCT(asn1);

	switch (spnego->type) {
	case SPNEGO_NEG_TOKEN_INIT:
		asn1_push_tag(&asn1, ASN1_APPLICATION(0));
		asn1_write_OID(&asn1, OID_SPNEGO);
		write_negTokenInit(&asn1, &spnego->negTokenInit);
		asn1_pop_tag(&asn1);
		break;
	case SPNEGO_NEG_TOKEN_TARG:
		write_negTokenTarg(&asn1, &spnego->negTokenTarg);
		break;
	default:
		asn1.has_error = True;
		break;
	}

	if (!asn1.has_error) {
		*blob = data_blob(asn1.data, asn1.length);
		ret = asn1.ofs;
	}
	asn1_free(&asn1);

	return ret;
}
示例#7
0
文件: clispnego.c 项目: hajuuk/R7000
/*
  parse a krb5 GSS-API wrapper packet giving a ticket
*/
BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
{
	BOOL ret;
	ASN1_DATA data;
	int data_remaining;

	asn1_load(&data, blob);
	asn1_start_tag(&data, ASN1_APPLICATION(0));
	asn1_check_OID(&data, OID_KERBEROS5);

	data_remaining = asn1_tag_remaining(&data);

	if (data_remaining < 3) {
		data.has_error = True;
	} else {
		asn1_read(&data, tok_id, 2);
		data_remaining -= 2;
		*ticket = data_blob(NULL, data_remaining);
		asn1_read(&data, ticket->data, ticket->length);
	}

	asn1_end_tag(&data);

	ret = !data.has_error;

	asn1_free(&data);

	return ret;
}
示例#8
0
/*
  generate a krb5 GSS-API wrapper packet given a ticket
*/
DATA_BLOB spnego_gen_krb5_wrap(TALLOC_CTX *ctx, const DATA_BLOB ticket, const uint8 tok_id[2])
{
    ASN1_DATA *data;
    DATA_BLOB ret;

    data = asn1_init(talloc_tos());
    if (data == NULL) {
        return data_blob_null;
    }

    asn1_push_tag(data, ASN1_APPLICATION(0));
    asn1_write_OID(data, OID_KERBEROS5);

    asn1_write(data, tok_id, 2);
    asn1_write(data, ticket.data, ticket.length);
    asn1_pop_tag(data);

    if (data->has_error) {
        DEBUG(1,("Failed to build krb5 wrapper at offset %d\n", (int)data->ofs));
    }

    ret = data_blob_talloc(ctx, data->data, data->length);
    asn1_free(data);

    return ret;
}
示例#9
0
/*
  generate a krb5 GSS-API wrapper packet given a ticket
*/
static DATA_BLOB gensec_gssapi_gen_krb5_wrap(TALLOC_CTX *mem_ctx, const DATA_BLOB *ticket, const uint8_t tok_id[2])
{
    struct asn1_data *data;
    DATA_BLOB ret;

    data = asn1_init(mem_ctx);
    if (!data || !ticket->data) {
        return data_blob(NULL,0);
    }

    asn1_push_tag(data, ASN1_APPLICATION(0));
    asn1_write_OID(data, GENSEC_OID_KERBEROS5);

    asn1_write(data, tok_id, 2);
    asn1_write(data, ticket->data, ticket->length);
    asn1_pop_tag(data);

    if (data->has_error) {
        DEBUG(1,("Failed to build krb5 wrapper at offset %d\n", (int)data->ofs));
        asn1_free(data);
        return data_blob(NULL,0);
    }

    ret = data_blob_talloc(mem_ctx, data->data, data->length);
    asn1_free(data);

    return ret;
}
示例#10
0
ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data *token)
{
    struct asn1_data *asn1;
    ssize_t ret = -1;
    uint8_t context;

    ZERO_STRUCTP(token);

    if (data.length == 0) {
        return ret;
    }

    asn1 = asn1_init(mem_ctx);
    if (asn1 == NULL) {
        return -1;
    }

    asn1_load(asn1, data);

    if (!asn1_peek_uint8(asn1, &context)) {
        asn1->has_error = true;
    } else {
        switch (context) {
        case ASN1_APPLICATION(0):
            asn1_start_tag(asn1, ASN1_APPLICATION(0));
            asn1_check_OID(asn1, GENSEC_OID_SPNEGO);
            if (read_negTokenInit(asn1, mem_ctx, &token->negTokenInit)) {
                token->type = SPNEGO_NEG_TOKEN_INIT;
            }
            asn1_end_tag(asn1);
            break;
        case ASN1_CONTEXT(1):
            if (read_negTokenTarg(asn1, mem_ctx, &token->negTokenTarg)) {
                token->type = SPNEGO_NEG_TOKEN_TARG;
            }
            break;
        default:
            asn1->has_error = true;
            break;
        }
    }

    if (!asn1->has_error) ret = asn1->ofs;
    asn1_free(asn1);

    return ret;
}
示例#11
0
DATA_BLOB spnego_gen_negTokenInit(TALLOC_CTX *ctx,
                                  const char *OIDs[],
                                  DATA_BLOB *psecblob,
                                  const char *principal)
{
    int i;
    ASN1_DATA *data;
    DATA_BLOB ret;

    data = asn1_init(talloc_tos());
    if (data == NULL) {
        return data_blob_null;
    }

    asn1_push_tag(data,ASN1_APPLICATION(0));
    asn1_write_OID(data,OID_SPNEGO);
    asn1_push_tag(data,ASN1_CONTEXT(0));
    asn1_push_tag(data,ASN1_SEQUENCE(0));

    asn1_push_tag(data,ASN1_CONTEXT(0));
    asn1_push_tag(data,ASN1_SEQUENCE(0));
    for (i=0; OIDs[i]; i++) {
        asn1_write_OID(data,OIDs[i]);
    }
    asn1_pop_tag(data);
    asn1_pop_tag(data);

    if (psecblob && psecblob->length && psecblob->data) {
        asn1_push_tag(data, ASN1_CONTEXT(2));
        asn1_write_OctetString(data,psecblob->data,
                               psecblob->length);
        asn1_pop_tag(data);
    }

    if (principal) {
        asn1_push_tag(data, ASN1_CONTEXT(3));
        asn1_push_tag(data, ASN1_SEQUENCE(0));
        asn1_push_tag(data, ASN1_CONTEXT(0));
        asn1_write_GeneralString(data,principal);
        asn1_pop_tag(data);
        asn1_pop_tag(data);
        asn1_pop_tag(data);
    }

    asn1_pop_tag(data);
    asn1_pop_tag(data);

    asn1_pop_tag(data);

    if (data->has_error) {
        DEBUG(1,("Failed to build negTokenInit at offset %d\n", (int)data->ofs));
    }

    ret = data_blob_talloc(ctx, data->data, data->length);
    asn1_free(data);

    return ret;
}
示例#12
0
文件: clispnego.c 项目: hajuuk/R7000
/*
  generate a negTokenInit packet given a GUID, a list of supported
  OIDs (the mechanisms) and a principal name string 
*/
DATA_BLOB spnego_gen_negTokenInit(uint8 guid[16], 
				  const char *OIDs[], 
				  const char *principal)
{
	int i;
	ASN1_DATA data;
	DATA_BLOB ret;

	memset(&data, 0, sizeof(data));

	asn1_write(&data, guid, 16);
	asn1_push_tag(&data,ASN1_APPLICATION(0));
	asn1_write_OID(&data,OID_SPNEGO);
	asn1_push_tag(&data,ASN1_CONTEXT(0));
	asn1_push_tag(&data,ASN1_SEQUENCE(0));

	asn1_push_tag(&data,ASN1_CONTEXT(0));
	asn1_push_tag(&data,ASN1_SEQUENCE(0));
	for (i=0; OIDs[i]; i++) {
		asn1_write_OID(&data,OIDs[i]);
	}
	asn1_pop_tag(&data);
	asn1_pop_tag(&data);

	asn1_push_tag(&data, ASN1_CONTEXT(3));
	asn1_push_tag(&data, ASN1_SEQUENCE(0));
	asn1_push_tag(&data, ASN1_CONTEXT(0));
	asn1_write_GeneralString(&data,principal);
	asn1_pop_tag(&data);
	asn1_pop_tag(&data);
	asn1_pop_tag(&data);

	asn1_pop_tag(&data);
	asn1_pop_tag(&data);

	asn1_pop_tag(&data);

	if (data.has_error) {
		DEBUG(1,("Failed to build negTokenInit at offset %d\n", (int)data.ofs));
		asn1_free(&data);
	}

	ret = data_blob(data.data, data.length);
	asn1_free(&data);

	return ret;
}
/*
  magic check a GSS-API wrapper packet for an Kerberos OID
*/
static bool gensec_gssapi_check_oid(const DATA_BLOB *blob, const char *oid)
{
	bool ret;
	struct asn1_data *data = asn1_init(NULL);

	if (!data) return false;

	asn1_load(data, *blob);
	asn1_start_tag(data, ASN1_APPLICATION(0));
	asn1_check_OID(data, oid);

	ret = !data->has_error;

	asn1_free(data);

	return ret;
}
示例#14
0
文件: clispnego.c 项目: hajuuk/R7000
/*
  parse a negTokenInit packet giving a GUID, a list of supported
  OIDs (the mechanisms) and a principal name string 
*/
BOOL spnego_parse_negTokenInit(DATA_BLOB blob,
			       char *OIDs[ASN1_MAX_OIDS], 
			       char **principal)
{
	int i;
	BOOL ret;
	ASN1_DATA data;

	asn1_load(&data, blob);

	asn1_start_tag(&data,ASN1_APPLICATION(0));
	asn1_check_OID(&data,OID_SPNEGO);
	asn1_start_tag(&data,ASN1_CONTEXT(0));
	asn1_start_tag(&data,ASN1_SEQUENCE(0));

	asn1_start_tag(&data,ASN1_CONTEXT(0));
	asn1_start_tag(&data,ASN1_SEQUENCE(0));
	for (i=0; asn1_tag_remaining(&data) > 0 && i < ASN1_MAX_OIDS; i++) {
		char *oid_str = NULL;
		asn1_read_OID(&data,&oid_str);
		OIDs[i] = oid_str;
	}
	OIDs[i] = NULL;
	asn1_end_tag(&data);
	asn1_end_tag(&data);

	asn1_start_tag(&data, ASN1_CONTEXT(3));
	asn1_start_tag(&data, ASN1_SEQUENCE(0));
	asn1_start_tag(&data, ASN1_CONTEXT(0));
	asn1_read_GeneralString(&data,principal);
	asn1_end_tag(&data);
	asn1_end_tag(&data);
	asn1_end_tag(&data);

	asn1_end_tag(&data);
	asn1_end_tag(&data);

	asn1_end_tag(&data);

	ret = !data.has_error;
	asn1_free(&data);
	return ret;
}
示例#15
0
文件: clispnego.c 项目: hajuuk/R7000
/*
  generate a negTokenTarg packet given a list of OIDs and a security blob
*/
DATA_BLOB gen_negTokenTarg(const char *OIDs[], DATA_BLOB blob)
{
	int i;
	ASN1_DATA data;
	DATA_BLOB ret;

	memset(&data, 0, sizeof(data));

	asn1_push_tag(&data, ASN1_APPLICATION(0));
	asn1_write_OID(&data,OID_SPNEGO);
	asn1_push_tag(&data, ASN1_CONTEXT(0));
	asn1_push_tag(&data, ASN1_SEQUENCE(0));

	asn1_push_tag(&data, ASN1_CONTEXT(0));
	asn1_push_tag(&data, ASN1_SEQUENCE(0));
	for (i=0; OIDs[i]; i++) {
		asn1_write_OID(&data,OIDs[i]);
	}
	asn1_pop_tag(&data);
	asn1_pop_tag(&data);

	asn1_push_tag(&data, ASN1_CONTEXT(2));
	asn1_write_OctetString(&data,blob.data,blob.length);
	asn1_pop_tag(&data);

	asn1_pop_tag(&data);
	asn1_pop_tag(&data);

	asn1_pop_tag(&data);

	if (data.has_error) {
		DEBUG(1,("Failed to build negTokenTarg at offset %d\n", (int)data.ofs));
		asn1_free(&data);
	}

	ret = data_blob(data.data, data.length);
	asn1_free(&data);

	return ret;
}
示例#16
0
文件: clispnego.c 项目: hajuuk/R7000
/*
  parse a negTokenTarg packet giving a list of OIDs and a security blob
*/
BOOL parse_negTokenTarg(DATA_BLOB blob, char *OIDs[ASN1_MAX_OIDS], DATA_BLOB *secblob)
{
	int i;
	ASN1_DATA data;

	asn1_load(&data, blob);
	asn1_start_tag(&data, ASN1_APPLICATION(0));
	asn1_check_OID(&data,OID_SPNEGO);
	asn1_start_tag(&data, ASN1_CONTEXT(0));
	asn1_start_tag(&data, ASN1_SEQUENCE(0));

	asn1_start_tag(&data, ASN1_CONTEXT(0));
	asn1_start_tag(&data, ASN1_SEQUENCE(0));
	for (i=0; asn1_tag_remaining(&data) > 0 && i < ASN1_MAX_OIDS; i++) {
		char *oid_str = NULL;
		asn1_read_OID(&data,&oid_str);
		OIDs[i] = oid_str;
	}
	OIDs[i] = NULL;
	asn1_end_tag(&data);
	asn1_end_tag(&data);

	asn1_start_tag(&data, ASN1_CONTEXT(2));
	asn1_read_OctetString(&data,secblob);
	asn1_end_tag(&data);

	asn1_end_tag(&data);
	asn1_end_tag(&data);

	asn1_end_tag(&data);

	if (data.has_error) {
		DEBUG(1,("Failed to parse negTokenTarg at offset %d\n", (int)data.ofs));
		asn1_free(&data);
		return False;
	}

	asn1_free(&data);
	return True;
}
示例#17
0
/*
  parse a krb5 GSS-API wrapper packet giving a ticket
*/
bool spnego_parse_krb5_wrap(TALLOC_CTX *ctx, DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2])
{
    bool ret;
    ASN1_DATA *data;
    int data_remaining;

    data = asn1_init(talloc_tos());
    if (data == NULL) {
        return false;
    }

    asn1_load(data, blob);
    asn1_start_tag(data, ASN1_APPLICATION(0));
    asn1_check_OID(data, OID_KERBEROS5);

    data_remaining = asn1_tag_remaining(data);

    if (data_remaining < 3) {
        data->has_error = True;
    } else {
        asn1_read(data, tok_id, 2);
        data_remaining -= 2;
        *ticket = data_blob_talloc(ctx, NULL, data_remaining);
        asn1_read(data, ticket->data, ticket->length);
    }

    asn1_end_tag(data);

    ret = !data->has_error;

    if (data->has_error) {
        data_blob_free(ticket);
    }

    asn1_free(data);

    return ret;
}
示例#18
0
/*
  receive a cldap netlogon reply
*/
static int recv_cldap_netlogon(int sock, struct cldap_netlogon_reply *reply)
{
	int ret;
	ASN1_DATA data;
	DATA_BLOB blob;
	DATA_BLOB os1, os2, os3;
	uint32 i1;
	char *p;

	blob = data_blob(NULL, 8192);

	ret = read(sock, blob.data, blob.length);

	if (ret <= 0) {
		d_printf("no reply received to cldap netlogon\n");
		return -1;
	}
	blob.length = ret;

	asn1_load(&data, blob);
	asn1_start_tag(&data, ASN1_SEQUENCE(0));
	asn1_read_Integer(&data, &i1);
	asn1_start_tag(&data, ASN1_APPLICATION(4));
	asn1_read_OctetString(&data, &os1);
	asn1_start_tag(&data, ASN1_SEQUENCE(0));
	asn1_start_tag(&data, ASN1_SEQUENCE(0));
	asn1_read_OctetString(&data, &os2);
	asn1_start_tag(&data, ASN1_SET);
	asn1_read_OctetString(&data, &os3);
	asn1_end_tag(&data);
	asn1_end_tag(&data);
	asn1_end_tag(&data);
	asn1_end_tag(&data);
	asn1_end_tag(&data);

	if (data.has_error) {
		d_printf("Failed to parse cldap reply\n");
		return -1;
	}

	p = (char *)os3.data;

	reply->type = IVAL(p, 0); p += 4;
	reply->flags = IVAL(p, 0); p += 4;

	memcpy(&reply->guid.info, p, UUID_FLAT_SIZE);
	p += UUID_FLAT_SIZE;

	p += pull_netlogon_string(reply->forest, p, (const char *)os3.data);
	p += pull_netlogon_string(reply->domain, p, (const char *)os3.data);
	p += pull_netlogon_string(reply->hostname, p, (const char *)os3.data);
	p += pull_netlogon_string(reply->netbios_domain, p, (const char *)os3.data);
	p += pull_netlogon_string(reply->netbios_hostname, p, (const char *)os3.data);
	p += pull_netlogon_string(reply->unk, p, (const char *)os3.data);

	if (reply->type == SAMLOGON_AD_R) {
		p += pull_netlogon_string(reply->user_name, p, (const char *)os3.data);
	} else {
		*reply->user_name = 0;
	}

	p += pull_netlogon_string(reply->site_name, p, (const char *)os3.data);
	p += pull_netlogon_string(reply->site_name_2, p, (const char *)os3.data);

	reply->version = IVAL(p, 0);
	reply->lmnt_token = SVAL(p, 4);
	reply->lm20_token = SVAL(p, 6);

	data_blob_free(&os1);
	data_blob_free(&os2);
	data_blob_free(&os3);
	data_blob_free(&blob);
	
	return 0;
}
示例#19
0
static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
					char *outbuf,
					int length,int bufsize)
{
	uint8 *p;
	DATA_BLOB blob1;
	int ret;
	size_t bufrem;
	fstring native_os, native_lanman, primary_domain;
	char *p2;
	uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
	enum remote_arch_types ra_type = get_remote_arch();
	int vuid = SVAL(inbuf,smb_uid);
	user_struct *vuser = NULL;
	NTSTATUS status = NT_STATUS_OK;
	uint16 smbpid = SVAL(inbuf,smb_pid);

	DEBUG(3,("Doing spnego session setup\n"));

	if (global_client_caps == 0) {
		global_client_caps = IVAL(inbuf,smb_vwv10);

		if (!(global_client_caps & CAP_STATUS32)) {
			remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
		}

	}
		
	p = (uint8 *)smb_buf(inbuf);

	if (data_blob_len == 0) {
		/* an invalid request */
		return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
	}

	bufrem = smb_bufrem(inbuf, p);
	/* pull the spnego blob */
	blob1 = data_blob(p, MIN(bufrem, data_blob_len));

#if 0
	file_save("negotiate.dat", blob1.data, blob1.length);
#endif

	p2 = inbuf + smb_vwv13 + data_blob_len;
	p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
	p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
	p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
	DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", 
		native_os, native_lanman, primary_domain));

	if ( ra_type == RA_WIN2K ) {
		/* Vista sets neither the OS or lanman strings */

		if ( !strlen(native_os) && !strlen(native_lanman) )
			set_remote_arch(RA_VISTA);
		
		/* Windows 2003 doesn't set the native lanman string, 
		   but does set primary domain which is a bug I think */
			   
		if ( !strlen(native_lanman) ) {
			ra_lanman_string( primary_domain );
		} else {
			ra_lanman_string( native_lanman );
		}
	}
		
	vuser = get_partial_auth_user_struct(vuid);
	if (!vuser) {
		struct pending_auth_data *pad = get_pending_auth_data(smbpid);
		if (pad) {
			DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n",
				(unsigned int)pad->vuid ));
			vuid = pad->vuid;
			vuser = get_partial_auth_user_struct(vuid);
		}
	}

	if (!vuser) {
		vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL);
		if (vuid == UID_FIELD_INVALID ) {
			data_blob_free(&blob1);
			return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
		}
	
		vuser = get_partial_auth_user_struct(vuid);
	}

	if (!vuser) {
		data_blob_free(&blob1);
		return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
	}
	
	SSVAL(outbuf,smb_uid,vuid);

	/* Large (greater than 4k) SPNEGO blobs are split into multiple
	 * sessionsetup requests as the Windows limit on the security blob
	 * field is 4k. Bug #4400. JRA.
	 */

	status = check_spnego_blob_complete(smbpid, vuid, &blob1);
	if (!NT_STATUS_IS_OK(status)) {
		if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
			/* Real error - kill the intermediate vuid */
			invalidate_vuid(vuid);
		}
		data_blob_free(&blob1);
		return ERROR_NT(nt_status_squash(status));
	}

	if (blob1.data[0] == ASN1_APPLICATION(0)) {
		/* its a negTokenTarg packet */
		ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
					     &vuser->auth_ntlmssp_state);
		data_blob_free(&blob1);
		return ret;
	}

	if (blob1.data[0] == ASN1_CONTEXT(1)) {
		/* its a auth packet */
		ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1,
					&vuser->auth_ntlmssp_state);
		data_blob_free(&blob1);
		return ret;
	}

	if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
		DATA_BLOB chal;
		if (!vuser->auth_ntlmssp_state) {
			status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state);
			if (!NT_STATUS_IS_OK(status)) {
				/* Kill the intermediate vuid */
				invalidate_vuid(vuid);
				data_blob_free(&blob1);
				return ERROR_NT(nt_status_squash(status));
			}
		}

		status = auth_ntlmssp_update(vuser->auth_ntlmssp_state,
						blob1, &chal);
		
		data_blob_free(&blob1);
		
		reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, 
					   &vuser->auth_ntlmssp_state,
					   &chal, status, False);
		data_blob_free(&chal);
		return -1;
	}

	/* what sort of packet is this? */
	DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));

	data_blob_free(&blob1);

	return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE));
}
示例#20
0
/*
  receive a cldap netlogon reply
*/
static int recv_cldap_netlogon(TALLOC_CTX *mem_ctx,
			       int sock,
			       uint32_t *nt_version,
			       union nbt_cldap_netlogon **reply)
{
	int ret;
	ASN1_DATA data;
	DATA_BLOB blob = data_blob_null;
	DATA_BLOB os1 = data_blob_null;
	DATA_BLOB os2 = data_blob_null;
	DATA_BLOB os3 = data_blob_null;
	int i1;
	/* half the time of a regular ldap timeout, not less than 3 seconds. */
	unsigned int al_secs = MAX(3,lp_ldap_timeout()/2);
	union nbt_cldap_netlogon *r = NULL;

	blob = data_blob(NULL, 8192);
	if (blob.data == NULL) {
		DEBUG(1, ("data_blob failed\n"));
		errno = ENOMEM;
		return -1;
	}

	/* Setup timeout */
	gotalarm = 0;
	CatchSignal(SIGALRM, SIGNAL_CAST gotalarm_sig);
	alarm(al_secs);
	/* End setup timeout. */
 
	ret = read(sock, blob.data, blob.length);

	/* Teardown timeout. */
	CatchSignal(SIGALRM, SIGNAL_CAST SIG_IGN);
	alarm(0);

	if (ret <= 0) {
		DEBUG(1,("no reply received to cldap netlogon\n"));
		data_blob_free(&blob);
		return -1;
	}
	blob.length = ret;

	asn1_load(&data, blob);
	asn1_start_tag(&data, ASN1_SEQUENCE(0));
	asn1_read_Integer(&data, &i1);
	asn1_start_tag(&data, ASN1_APPLICATION(4));
	asn1_read_OctetString(&data, &os1);
	asn1_start_tag(&data, ASN1_SEQUENCE(0));
	asn1_start_tag(&data, ASN1_SEQUENCE(0));
	asn1_read_OctetString(&data, &os2);
	asn1_start_tag(&data, ASN1_SET);
	asn1_read_OctetString(&data, &os3);
	asn1_end_tag(&data);
	asn1_end_tag(&data);
	asn1_end_tag(&data);
	asn1_end_tag(&data);
	asn1_end_tag(&data);

	if (data.has_error) {
		data_blob_free(&blob);
		data_blob_free(&os1);
		data_blob_free(&os2);
		data_blob_free(&os3);
		asn1_free(&data);
		DEBUG(1,("Failed to parse cldap reply\n"));
		return -1;
	}

	r = TALLOC_ZERO_P(mem_ctx, union nbt_cldap_netlogon);
	if (!r) {
		errno = ENOMEM;
		data_blob_free(&os1);
		data_blob_free(&os2);
		data_blob_free(&os3);
		data_blob_free(&blob);
		return -1;
	}

	if (!pull_mailslot_cldap_reply(mem_ctx, &os3, r, nt_version)) {
		data_blob_free(&os1);
		data_blob_free(&os2);
		data_blob_free(&os3);
		data_blob_free(&blob);
		TALLOC_FREE(r);
		return -1;
	}

	data_blob_free(&os1);
	data_blob_free(&os2);
	data_blob_free(&os3);
	data_blob_free(&blob);
	
	asn1_free(&data);

	if (reply) {
		*reply = r;
	} else {
		TALLOC_FREE(r);
	}

	return 0;
}
示例#21
0
static NTSTATUS smbd_smb2_spnego_auth(struct smbd_smb2_session *session,
					struct smbd_smb2_request *smb2req,
					uint8_t in_security_mode,
					DATA_BLOB in_security_buffer,
					uint16_t *out_session_flags,
					DATA_BLOB *out_security_buffer,
					uint64_t *out_session_id)
{
	DATA_BLOB auth = data_blob_null;
	DATA_BLOB auth_out = data_blob_null;
	NTSTATUS status;

	if (!spnego_parse_auth(talloc_tos(), in_security_buffer, &auth)) {
		TALLOC_FREE(session);
		return NT_STATUS_LOGON_FAILURE;
	}

	if (auth.data[0] == ASN1_APPLICATION(0)) {
		/* Might be a second negTokenTarg packet */
		DATA_BLOB secblob_in = data_blob_null;
		char *kerb_mech = NULL;

		status = parse_spnego_mechanisms(talloc_tos(),
				in_security_buffer,
				&secblob_in, &kerb_mech);
		if (!NT_STATUS_IS_OK(status)) {
			TALLOC_FREE(session);
			return status;
		}

#ifdef HAVE_KRB5
		if (kerb_mech && ((lp_security()==SEC_ADS) ||
					USE_KERBEROS_KEYTAB) ) {
			status = smbd_smb2_session_setup_krb5(session,
					smb2req,
					in_security_mode,
					&secblob_in,
					kerb_mech,
					out_session_flags,
					out_security_buffer,
					out_session_id);

			data_blob_free(&secblob_in);
			TALLOC_FREE(kerb_mech);
			if (!NT_STATUS_IS_OK(status)) {
				TALLOC_FREE(session);
			}
			return status;
		}
#endif

		/* Can't blunder into NTLMSSP auth if we have
		 * a krb5 ticket. */

		if (kerb_mech) {
			DEBUG(3,("smb2: network "
				"misconfiguration, client sent us a "
				"krb5 ticket and kerberos security "
				"not enabled\n"));
			TALLOC_FREE(session);
			data_blob_free(&secblob_in);
			TALLOC_FREE(kerb_mech);
			return NT_STATUS_LOGON_FAILURE;
		}

		data_blob_free(&secblob_in);
	}

	if (session->auth_ntlmssp_state == NULL) {
		status = auth_ntlmssp_prepare(session->sconn->remote_address,
					    &session->auth_ntlmssp_state);
		if (!NT_STATUS_IS_OK(status)) {
			data_blob_free(&auth);
			TALLOC_FREE(session);
			return status;
		}

		auth_ntlmssp_want_feature(session->auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);

		status = auth_ntlmssp_start(session->auth_ntlmssp_state);
		if (!NT_STATUS_IS_OK(status)) {
			data_blob_free(&auth);
			TALLOC_FREE(session);
			return status;
		}
	}

	status = auth_ntlmssp_update(session->auth_ntlmssp_state,
				     talloc_tos(), auth,
				     &auth_out);
	/* If status is NT_STATUS_OK then we need to get the token.
	 * Map to guest is now internal to auth_ntlmssp */
	if (NT_STATUS_IS_OK(status)) {
		status = auth_ntlmssp_session_info(session,
						   session->auth_ntlmssp_state,
						   &session->session_info);
	}

	if (!NT_STATUS_IS_OK(status) &&
			!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		TALLOC_FREE(session->auth_ntlmssp_state);
		data_blob_free(&auth);
		TALLOC_FREE(session);
		return status;
	}

	data_blob_free(&auth);

	*out_security_buffer = spnego_gen_auth_response(smb2req,
				&auth_out, status, NULL);

	if (out_security_buffer->data == NULL) {
		TALLOC_FREE(session->auth_ntlmssp_state);
		TALLOC_FREE(session);
		return NT_STATUS_NO_MEMORY;
	}

	*out_session_id = session->vuid;

	if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
		return NT_STATUS_MORE_PROCESSING_REQUIRED;
	}

	/* We're done - claim the session. */
	return smbd_smb2_common_ntlmssp_auth_return(session,
						smb2req,
						in_security_mode,
						in_security_buffer,
						out_session_flags,
						out_session_id);
}
示例#22
0
static int reply_spnego_auth(connection_struct *conn, char *inbuf, char *outbuf,
			     uint16 vuid,
			     int length, int bufsize,
			     DATA_BLOB blob1,
			     AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
{
	DATA_BLOB auth = data_blob(NULL,0);
	DATA_BLOB auth_reply = data_blob(NULL,0);
	DATA_BLOB secblob = data_blob(NULL,0);
	NTSTATUS status = NT_STATUS_INVALID_PARAMETER;

	if (!spnego_parse_auth(blob1, &auth)) {
#if 0
		file_save("auth.dat", blob1.data, blob1.length);
#endif
		/* Kill the intermediate vuid */
		invalidate_vuid(vuid);

		return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
	}

	if (auth.data[0] == ASN1_APPLICATION(0)) {
		/* Might be a second negTokenTarg packet */

		BOOL got_krb5_mechanism = False;
		status = parse_spnego_mechanisms(auth, &secblob, &got_krb5_mechanism);
		if (NT_STATUS_IS_OK(status)) {
			DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n", (unsigned long)secblob.length));
#ifdef HAVE_KRB5
			if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) {
				BOOL destroy_vuid = True;
				int ret = reply_spnego_kerberos(conn, inbuf, outbuf, 
								length, bufsize, &secblob, &destroy_vuid);
				data_blob_free(&secblob);
				data_blob_free(&auth);
				if (destroy_vuid) {
					/* Kill the intermediate vuid */
					invalidate_vuid(vuid);
				}
				return ret;
			}
#endif
		}
	}

	/* If we get here it wasn't a negTokenTarg auth packet. */
	data_blob_free(&secblob);
	
	if (!*auth_ntlmssp_state) {
		/* Kill the intermediate vuid */
		invalidate_vuid(vuid);

		/* auth before negotiatiate? */
		return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER));
	}
	
	status = auth_ntlmssp_update(*auth_ntlmssp_state, 
					auth, &auth_reply);

	data_blob_free(&auth);

	reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, 
			     auth_ntlmssp_state,
			     &auth_reply, status, True);
		
	data_blob_free(&auth_reply);

	/* and tell smbd that we have already replied to this packet */
	return -1;
}
示例#23
0
/*
  parse a negTokenInit packet giving a GUID, a list of supported
  OIDs (the mechanisms) and a principal name string
*/
bool spnego_parse_negTokenInit(TALLOC_CTX *ctx,
                               DATA_BLOB blob,
                               char *OIDs[ASN1_MAX_OIDS],
                               char **principal,
                               DATA_BLOB *secblob)
{
    int i;
    bool ret;
    ASN1_DATA *data;

    data = asn1_init(talloc_tos());
    if (data == NULL) {
        return false;
    }

    asn1_load(data, blob);

    asn1_start_tag(data,ASN1_APPLICATION(0));

    asn1_check_OID(data,OID_SPNEGO);

    /* negTokenInit  [0]  NegTokenInit */
    asn1_start_tag(data,ASN1_CONTEXT(0));
    asn1_start_tag(data,ASN1_SEQUENCE(0));

    /* mechTypes [0] MechTypeList  OPTIONAL */

    /* Not really optional, we depend on this to decide
     * what mechanisms we have to work with. */

    asn1_start_tag(data,ASN1_CONTEXT(0));
    asn1_start_tag(data,ASN1_SEQUENCE(0));
    for (i=0; asn1_tag_remaining(data) > 0 && i < ASN1_MAX_OIDS-1; i++) {
        asn1_read_OID(data,ctx, &OIDs[i]);
        if (data->has_error) {
            break;
        }
    }
    OIDs[i] = NULL;
    asn1_end_tag(data);
    asn1_end_tag(data);

    if (principal) {
        *principal = NULL;
    }
    if (secblob) {
        *secblob = data_blob_null;
    }

    /*
      Win7 + Live Sign-in Assistant attaches a mechToken
      ASN1_CONTEXT(2) to the negTokenInit packet
      which breaks our negotiation if we just assume
      the next tag is ASN1_CONTEXT(3).
    */

    if (asn1_peek_tag(data, ASN1_CONTEXT(1))) {
        uint8 flags;

        /* reqFlags [1] ContextFlags  OPTIONAL */
        asn1_start_tag(data, ASN1_CONTEXT(1));
        asn1_start_tag(data, ASN1_BIT_STRING);
        while (asn1_tag_remaining(data) > 0) {
            asn1_read_uint8(data, &flags);
        }
        asn1_end_tag(data);
        asn1_end_tag(data);
    }

    if (asn1_peek_tag(data, ASN1_CONTEXT(2))) {
        DATA_BLOB sblob = data_blob_null;
        /* mechToken [2] OCTET STRING  OPTIONAL */
        asn1_start_tag(data, ASN1_CONTEXT(2));
        asn1_read_OctetString(data, ctx, &sblob);
        asn1_end_tag(data);
        if (secblob) {
            *secblob = sblob;
        } else {
            data_blob_free(&sblob);
        }
    }

    if (asn1_peek_tag(data, ASN1_CONTEXT(3))) {
        char *princ = NULL;
        /* mechListMIC [3] OCTET STRING  OPTIONAL */
        asn1_start_tag(data, ASN1_CONTEXT(3));
        asn1_start_tag(data, ASN1_SEQUENCE(0));
        asn1_start_tag(data, ASN1_CONTEXT(0));
        asn1_read_GeneralString(data, ctx, &princ);
        asn1_end_tag(data);
        asn1_end_tag(data);
        asn1_end_tag(data);
        if (principal) {
            *principal = princ;
        } else {
            TALLOC_FREE(princ);
        }
    }

    asn1_end_tag(data);
    asn1_end_tag(data);

    asn1_end_tag(data);

    ret = !data->has_error;
    if (data->has_error) {
        int j;
        if (principal) {
            TALLOC_FREE(*principal);
        }
        if (secblob) {
            data_blob_free(secblob);
        }
        for(j = 0; j < i && j < ASN1_MAX_OIDS-1; j++) {
            TALLOC_FREE(OIDs[j]);
        }
    }

    asn1_free(data);
    return ret;
}
示例#24
0
static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
					char *outbuf,
					int length,int bufsize)
{
	uint8 *p;
	DATA_BLOB blob1;
	int ret;
	size_t bufrem;
	fstring native_os, native_lanman, primary_domain;
	char *p2;
	uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
	enum remote_arch_types ra_type = get_remote_arch();

	DEBUG(3,("Doing spnego session setup\n"));

	if (global_client_caps == 0) {
		global_client_caps = IVAL(inbuf,smb_vwv10);

		if (!(global_client_caps & CAP_STATUS32)) {
			remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
		}

	}
		
	p = (uint8 *)smb_buf(inbuf);

	if (data_blob_len == 0) {
		/* an invalid request */
		return ERROR_NT(NT_STATUS_LOGON_FAILURE);
	}

	bufrem = smb_bufrem(inbuf, p);
	/* pull the spnego blob */
	blob1 = data_blob(p, MIN(bufrem, data_blob_len));

#if 0
	file_save("negotiate.dat", blob1.data, blob1.length);
#endif

	p2 = inbuf + smb_vwv13 + data_blob_len;
	p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
	p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
	p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
	DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", 
		native_os, native_lanman, primary_domain));

	if ( ra_type == RA_WIN2K ) {
		/* Windows 2003 doesn't set the native lanman string, 
		   but does set primary domain which is a bug I think */
			   
		if ( !strlen(native_lanman) )
			ra_lanman_string( primary_domain );
		else
			ra_lanman_string( native_lanman );
	}
		
	if (blob1.data[0] == ASN1_APPLICATION(0)) {
		/* its a negTokenTarg packet */
		ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
		data_blob_free(&blob1);
		return ret;
	}

	if (blob1.data[0] == ASN1_CONTEXT(1)) {
		/* its a auth packet */
		ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
		data_blob_free(&blob1);
		return ret;
	}

	/* what sort of packet is this? */
	DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));

	data_blob_free(&blob1);

	return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
示例#25
0
/*
  do a cldap netlogon query
*/
static int send_cldap_netlogon(int sock, const char *domain, 
			       const char *hostname, unsigned ntversion)
{
	ASN1_DATA data;
	char ntver[4];
#ifdef CLDAP_USER_QUERY
	char aac[4];

	SIVAL(aac, 0, 0x00000180);
#endif
	SIVAL(ntver, 0, ntversion);

	memset(&data, 0, sizeof(data));

	asn1_push_tag(&data,ASN1_SEQUENCE(0));
	asn1_write_Integer(&data, 4);
	asn1_push_tag(&data, ASN1_APPLICATION(3));
	asn1_write_OctetString(&data, NULL, 0);
	asn1_write_enumerated(&data, 0);
	asn1_write_enumerated(&data, 0);
	asn1_write_Integer(&data, 0);
	asn1_write_Integer(&data, 0);
	asn1_write_BOOLEAN2(&data, False);
	asn1_push_tag(&data, ASN1_CONTEXT(0));

	if (domain) {
		asn1_push_tag(&data, ASN1_CONTEXT(3));
		asn1_write_OctetString(&data, "DnsDomain", 9);
		asn1_write_OctetString(&data, domain, strlen(domain));
		asn1_pop_tag(&data);
	}

	asn1_push_tag(&data, ASN1_CONTEXT(3));
	asn1_write_OctetString(&data, "Host", 4);
	asn1_write_OctetString(&data, hostname, strlen(hostname));
	asn1_pop_tag(&data);

#ifdef CLDAP_USER_QUERY
	asn1_push_tag(&data, ASN1_CONTEXT(3));
	asn1_write_OctetString(&data, "User", 4);
	asn1_write_OctetString(&data, "SAMBA$", 6);
	asn1_pop_tag(&data);

	asn1_push_tag(&data, ASN1_CONTEXT(3));
	asn1_write_OctetString(&data, "AAC", 4);
	asn1_write_OctetString(&data, aac, 4);
	asn1_pop_tag(&data);
#endif

	asn1_push_tag(&data, ASN1_CONTEXT(3));
	asn1_write_OctetString(&data, "NtVer", 5);
	asn1_write_OctetString(&data, ntver, 4);
	asn1_pop_tag(&data);

	asn1_pop_tag(&data);

	asn1_push_tag(&data,ASN1_SEQUENCE(0));
	asn1_write_OctetString(&data, "NetLogon", 8);
	asn1_pop_tag(&data);
	asn1_pop_tag(&data);
	asn1_pop_tag(&data);

	if (data.has_error) {
		DEBUG(2,("Failed to build cldap netlogon at offset %d\n", (int)data.ofs));
		asn1_free(&data);
		return -1;
	}

	if (write(sock, data.data, data.length) != (ssize_t)data.length) {
		DEBUG(2,("failed to send cldap query (%s)\n", strerror(errno)));
		asn1_free(&data);
		return -1;
	}

	asn1_free(&data);

	return 0;
}
示例#26
0
static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob)
{
	struct pending_auth_data *pad = NULL;
	ASN1_DATA data;
	size_t needed_len = 0;

	pad = get_pending_auth_data(smbpid);

	/* Ensure we have some data. */
	if (pblob->length == 0) {
		/* Caller can cope. */
		DEBUG(2,("check_spnego_blob_complete: zero blob length !\n"));
		delete_partial_auth(pad);
		return NT_STATUS_OK;
	}

	/* Were we waiting for more data ? */
	if (pad) {
		DATA_BLOB tmp_blob;
		size_t copy_len = MIN(65536, pblob->length);

		/* Integer wrap paranoia.... */

		if (pad->partial_data.length + copy_len < pad->partial_data.length ||
		    pad->partial_data.length + copy_len < copy_len) {

			DEBUG(2,("check_spnego_blob_complete: integer wrap "
				"pad->partial_data.length = %u, "
				"copy_len = %u\n",
				(unsigned int)pad->partial_data.length,
				(unsigned int)copy_len ));

			delete_partial_auth(pad);
			return NT_STATUS_INVALID_PARAMETER;
		}

		DEBUG(10,("check_spnego_blob_complete: "
			"pad->partial_data.length = %u, "
			"pad->needed_len = %u, "
			"copy_len = %u, "
			"pblob->length = %u,\n",
			(unsigned int)pad->partial_data.length,
			(unsigned int)pad->needed_len,
			(unsigned int)copy_len,
			(unsigned int)pblob->length ));

		tmp_blob = data_blob(NULL,
				pad->partial_data.length + copy_len);

		/* Concatenate the two (up to copy_len) bytes. */
		memcpy(tmp_blob.data,
			pad->partial_data.data,
			pad->partial_data.length);
		memcpy(tmp_blob.data + pad->partial_data.length,
			pblob->data,
			copy_len);

		/* Replace the partial data. */
		data_blob_free(&pad->partial_data);
		pad->partial_data = tmp_blob;
		ZERO_STRUCT(tmp_blob);

		/* Are we done ? */
		if (pblob->length >= pad->needed_len) {
			/* Yes, replace pblob. */
			data_blob_free(pblob);
			*pblob = pad->partial_data;
			ZERO_STRUCT(pad->partial_data);
			delete_partial_auth(pad);
			return NT_STATUS_OK;
		}

		/* Still need more data. */
		pad->needed_len -= copy_len;
		return NT_STATUS_MORE_PROCESSING_REQUIRED;
	}

	if ((pblob->data[0] != ASN1_APPLICATION(0)) &&
	    (pblob->data[0] != ASN1_CONTEXT(1))) {
		/* Not something we can determine the
		 * length of.
		 */
		return NT_STATUS_OK;
	}

	/* This is a new SPNEGO sessionsetup - see if
	 * the data given in this blob is enough.
	 */

	asn1_load(&data, *pblob);
	asn1_start_tag(&data, pblob->data[0]);
	if (data.has_error || data.nesting == NULL) {
		asn1_free(&data);
		/* Let caller catch. */
		return NT_STATUS_OK;
	}

	/* Integer wrap paranoia.... */

	if (data.nesting->taglen + data.nesting->start < data.nesting->taglen ||
	    data.nesting->taglen + data.nesting->start < data.nesting->start) {

		DEBUG(2,("check_spnego_blob_complete: integer wrap "
			"data.nesting->taglen = %u, "
			"data.nesting->start = %u\n",
			(unsigned int)data.nesting->taglen,
			(unsigned int)data.nesting->start ));

		asn1_free(&data);
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* Total length of the needed asn1 is the tag length
	 * plus the current offset. */

	needed_len = data.nesting->taglen + data.nesting->start;
	asn1_free(&data);

	DEBUG(10,("check_spnego_blob_complete: needed_len = %u, "
		"pblob->length = %u\n",
		(unsigned int)needed_len,
		(unsigned int)pblob->length ));

	if (needed_len <= pblob->length) {
		/* Nothing to do - blob is complete. */
		return NT_STATUS_OK;
	}

	/* Refuse the blob if it's bigger than 64k. */
	if (needed_len > 65536) {
		DEBUG(2,("check_spnego_blob_complete: needed_len too large (%u)\n",
			(unsigned int)needed_len ));
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* We must store this blob until complete. */
	pad = SMB_MALLOC(sizeof(struct pending_auth_data));
	if (!pad) {
		return NT_STATUS_NO_MEMORY;
	}
	pad->needed_len = needed_len - pblob->length;
	pad->partial_data = data_blob(pblob->data, pblob->length);
	if (pad->partial_data.data == NULL) {
		SAFE_FREE(pad);
		return NT_STATUS_NO_MEMORY;
	}
	pad->smbpid = smbpid;
	pad->vuid = vuid;
	DLIST_ADD(pd_list, pad);

	return NT_STATUS_MORE_PROCESSING_REQUIRED;
}
示例#27
0
DATA_BLOB spnego_gen_negTokenInit(TALLOC_CTX *ctx,
				  const char *OIDs[],
				  DATA_BLOB *psecblob,
				  const char *principal)
{
	int i;
	ASN1_DATA *data;
	DATA_BLOB ret = data_blob_null;

	data = asn1_init(talloc_tos());
	if (data == NULL) {
		return data_blob_null;
	}

	if (!asn1_push_tag(data,ASN1_APPLICATION(0))) goto err;
	if (!asn1_write_OID(data,OID_SPNEGO)) goto err;
	if (!asn1_push_tag(data,ASN1_CONTEXT(0))) goto err;
	if (!asn1_push_tag(data,ASN1_SEQUENCE(0))) goto err;

	if (!asn1_push_tag(data,ASN1_CONTEXT(0))) goto err;
	if (!asn1_push_tag(data,ASN1_SEQUENCE(0))) goto err;
	for (i=0; OIDs[i]; i++) {
		if (!asn1_write_OID(data,OIDs[i])) goto err;
	}
	if (!asn1_pop_tag(data)) goto err;
	if (!asn1_pop_tag(data)) goto err;

	if (psecblob && psecblob->length && psecblob->data) {
		if (!asn1_push_tag(data, ASN1_CONTEXT(2))) goto err;
		if (!asn1_write_OctetString(data,psecblob->data,
			psecblob->length)) goto err;
		if (!asn1_pop_tag(data)) goto err;
	}

	if (principal) {
		if (!asn1_push_tag(data, ASN1_CONTEXT(3))) goto err;
		if (!asn1_push_tag(data, ASN1_SEQUENCE(0))) goto err;
		if (!asn1_push_tag(data, ASN1_CONTEXT(0))) goto err;
		if (!asn1_write_GeneralString(data,principal)) goto err;
		if (!asn1_pop_tag(data)) goto err;
		if (!asn1_pop_tag(data)) goto err;
		if (!asn1_pop_tag(data)) goto err;
	}

	if (!asn1_pop_tag(data)) goto err;
	if (!asn1_pop_tag(data)) goto err;

	if (!asn1_pop_tag(data)) goto err;

	if (!asn1_extract_blob(data, ctx, &ret)) {
		goto err;
	}

  err:

	if (asn1_has_error(data)) {
		DEBUG(1, ("Failed to build negTokenInit at offset %d\n",
			  (int)asn1_current_ofs(data)));
	}

	asn1_free(data);

	return ret;
}
示例#28
0
文件: sesssetup.c 项目: hajuuk/R7000
static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf,
					char *outbuf,
					int length,int bufsize)
{
	uint8 *p;
	DATA_BLOB blob1;
	int ret;
	size_t bufrem;
	fstring native_os, native_lanman, primary_domain;
	char *p2;
	uint16 data_blob_len = SVAL(inbuf, smb_vwv7);
	enum remote_arch_types ra_type = get_remote_arch();

	DEBUG(3,("Doing spnego session setup\n"));

	if (global_client_caps == 0) {
		global_client_caps = IVAL(inbuf,smb_vwv10);

		if (!(global_client_caps & CAP_STATUS32)) {
			remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES);
		}

	}
		
	p = (uint8 *)smb_buf(inbuf);

	if (data_blob_len == 0) {
		/* an invalid request */
		return ERROR_NT(NT_STATUS_LOGON_FAILURE);
	}

	bufrem = smb_bufrem(inbuf, p);
	/* pull the spnego blob */
	blob1 = data_blob(p, MIN(bufrem, data_blob_len));

#if 0
	file_save("negotiate.dat", blob1.data, blob1.length);
#endif

	p2 = inbuf + smb_vwv13 + data_blob_len;
	p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE);
	p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE);
	p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE);
	DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", 
		native_os, native_lanman, primary_domain));

	if ( ra_type == RA_WIN2K ) {
		/* Windows 2003 doesn't set the native lanman string, 
		   but does set primary domain which is a bug I think */
			   
		if ( !strlen(native_lanman) )
			ra_lanman_string( primary_domain );
		else
			ra_lanman_string( native_lanman );
	}
		
	if (blob1.data[0] == ASN1_APPLICATION(0)) {
		/* its a negTokenTarg packet */
		ret = reply_spnego_negotiate(conn, inbuf, outbuf, length, bufsize, blob1);
		data_blob_free(&blob1);
		return ret;
	}

	if (blob1.data[0] == ASN1_CONTEXT(1)) {
		/* its a auth packet */
		ret = reply_spnego_auth(conn, inbuf, outbuf, length, bufsize, blob1);
		data_blob_free(&blob1);
		return ret;
	}

	/* Foxconn modified start pling 12/29/2011 */
	/* Fix Android partial auth issue.
	 * Port from Samba 3.0.24 (used by WNDR3800) */
	if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
		DATA_BLOB chal;
		NTSTATUS nt_status;
		if (!global_ntlmssp_state) {
	    	nt_status = auth_ntlmssp_start(&global_ntlmssp_state);
			if (!NT_STATUS_IS_OK(nt_status)) {
				return ERROR_NT(nt_status_squash(nt_status));
			}
		}

		nt_status = auth_ntlmssp_update(global_ntlmssp_state,
						blob1, &chal);
		
		data_blob_free(&blob1);
		
		reply_spnego_ntlmssp(conn, inbuf, outbuf, 
					   &global_ntlmssp_state,
					   &chal, nt_status, False);
		data_blob_free(&chal);
		return -1;
	}
    /* Foxconn added end pling 12/29/2011 */

	/* what sort of packet is this? */
	DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));

	data_blob_free(&blob1);

	return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}