⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pac.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
		 krb5_const_principal principal){    krb5_error_code ret;    krb5_principal p2;    uint32_t time1, time2;    krb5_storage *sp;    uint16_t len;    char *s;    sp = krb5_storage_from_readonly_mem((const char *)data->data + logon_name->offset_lo,					logon_name->buffersize);    if (sp == NULL) {	krb5_set_error_string(context, "Out of memory");	return ENOMEM;    }    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);    CHECK(ret, krb5_ret_uint32(sp, &time1), out);    CHECK(ret, krb5_ret_uint32(sp, &time2), out);    {	uint64_t t1, t2;	t1 = unix2nttime(authtime);	t2 = ((uint64_t)time2 << 32) | time1;	if (t1 != t2) {	    krb5_storage_free(sp);	    krb5_set_error_string(context, "PAC timestamp mismatch");	    return EINVAL;	}    }    CHECK(ret, krb5_ret_uint16(sp, &len), out);    if (len == 0) {	krb5_storage_free(sp);	krb5_set_error_string(context, "PAC logon name length missing");	return EINVAL;    }    s = malloc(len);    if (s == NULL) {	krb5_storage_free(sp);	krb5_set_error_string(context, "Out of memory");	return ENOMEM;    }    ret = krb5_storage_read(sp, s, len);    if (ret != len) {	krb5_storage_free(sp);	krb5_set_error_string(context, "Failed to read PAC logon name");	return EINVAL;    }    krb5_storage_free(sp);    {	size_t ucs2len = len / 2;	uint16_t *ucs2;	size_t u8len;	unsigned int flags = WIND_RW_LE;	ucs2 = malloc(sizeof(ucs2[0]) * ucs2len);	if (ucs2 == NULL) {	    krb5_set_error_string(context, "malloc: out of memory");	    return ENOMEM;	}	ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len);	free(s);	if (ret) {	    free(ucs2);	    krb5_set_error_string(context, "Failed to convert string to UCS-2");	    return ret;	}	ret = wind_ucs2utf8_length(ucs2, ucs2len, &u8len);	if (ret) {	    free(ucs2);	    krb5_set_error_string(context, "Failed to count length of UCS-2 string");	    return ret;	}	u8len += 1; /* Add space for NUL */	s = malloc(u8len);	if (s == NULL) {	    free(ucs2);	    krb5_set_error_string(context, "malloc: out of memory");	    return ENOMEM;	}	ret = wind_ucs2utf8(ucs2, ucs2len, s, &u8len);	free(ucs2);	if (ret) {	    krb5_set_error_string(context, "Failed to convert to UTF-8");	    return ret;	}    }    ret = krb5_parse_name_flags(context, s, KRB5_PRINCIPAL_PARSE_NO_REALM, &p2);    free(s);    if (ret)	return ret;        if (krb5_principal_compare_any_realm(context, principal, p2) != TRUE) {	krb5_set_error_string(context, "PAC logon name mismatch");	ret = EINVAL;    }    krb5_free_principal(context, p2);    return ret;out:    return ret;}/* * */static krb5_error_codebuild_logon_name(krb5_context context, 		 time_t authtime,		 krb5_const_principal principal, 		 krb5_data *logon){    krb5_error_code ret;    krb5_storage *sp;    uint64_t t;    char *s, *s2;    size_t i, len;    t = unix2nttime(authtime);    krb5_data_zero(logon);    sp = krb5_storage_emem();    if (sp == NULL) {	krb5_set_error_string(context, "out of memory");	return ENOMEM;    }    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);    CHECK(ret, krb5_store_uint32(sp, t & 0xffffffff), out);    CHECK(ret, krb5_store_uint32(sp, t >> 32), out);    ret = krb5_unparse_name_flags(context, principal,				  KRB5_PRINCIPAL_UNPARSE_NO_REALM, &s);    if (ret)	goto out;    len = strlen(s);        CHECK(ret, krb5_store_uint16(sp, len * 2), out);#if 1 /* cheat for now */    s2 = malloc(len * 2);    if (s2 == NULL) {	ret = ENOMEM;	free(s);	goto out;    }    for (i = 0; i < len; i++) {	s2[i * 2] = s[i];	s2[i * 2 + 1] = 0;    }    free(s);#else    /* write libwind code here */#endif    ret = krb5_storage_write(sp, s2, len * 2);    free(s2);    if (ret != len * 2) {	ret = ENOMEM;	goto out;    }    ret = krb5_storage_to_data(sp, logon);    if (ret)	goto out;    krb5_storage_free(sp);    return 0;out:    krb5_storage_free(sp);    return ret;}/* * */krb5_error_codekrb5_pac_verify(krb5_context context, 		const krb5_pac pac,		time_t authtime,		krb5_const_principal principal,		const krb5_keyblock *server,		const krb5_keyblock *privsvr){    krb5_error_code ret;    if (pac->server_checksum == NULL) {	krb5_set_error_string(context, "PAC missing server checksum");	return EINVAL;    }    if (pac->privsvr_checksum == NULL) {	krb5_set_error_string(context, "PAC missing kdc checksum");	return EINVAL;    }    if (pac->logon_name == NULL) {	krb5_set_error_string(context, "PAC missing logon name");	return EINVAL;    }    ret = verify_logonname(context, 			   pac->logon_name,			   &pac->data,			   authtime,			   principal);    if (ret)	return ret;    /*      * in the service case, clean out data option of the privsvr and     * server checksum before checking the checksum.     */    {	krb5_data *copy;	ret = krb5_copy_data(context, &pac->data, &copy);	if (ret)	    return ret;	if (pac->server_checksum->buffersize < 4)	    return EINVAL;	if (pac->privsvr_checksum->buffersize < 4)	    return EINVAL;	memset((char *)copy->data + pac->server_checksum->offset_lo + 4,	       0,	       pac->server_checksum->buffersize - 4);	memset((char *)copy->data + pac->privsvr_checksum->offset_lo + 4,	       0,	       pac->privsvr_checksum->buffersize - 4);	ret = verify_checksum(context,			      pac->server_checksum,			      &pac->data,			      copy->data,			      copy->length,			      server);	krb5_free_data(context, copy);	if (ret)	    return ret;    }    if (privsvr) {	ret = verify_checksum(context,			      pac->privsvr_checksum,			      &pac->data,			      (char *)pac->data.data			      + pac->server_checksum->offset_lo + 4,			      pac->server_checksum->buffersize - 4,			      privsvr);	if (ret)	    return ret;    }    return 0;}/* * */static krb5_error_codefill_zeros(krb5_context context, krb5_storage *sp, size_t len){    ssize_t sret;    size_t l;    while (len) {	l = len;	if (l > sizeof(zeros))	    l = sizeof(zeros);	sret = krb5_storage_write(sp, zeros, l);	if (sret <= 0) {	    krb5_set_error_string(context, "out of memory");	    return ENOMEM;	}	len -= sret;    }    return 0;}static krb5_error_codepac_checksum(krb5_context context, 	     const krb5_keyblock *key,	     uint32_t *cksumtype,	     size_t *cksumsize){    krb5_cksumtype cktype;    krb5_error_code ret;    krb5_crypto crypto = NULL;    ret = krb5_crypto_init(context, key, 0, &crypto);    if (ret)	return ret;    ret = krb5_crypto_get_checksum_type(context, crypto, &cktype);    ret = krb5_crypto_destroy(context, crypto);    if (ret)	return ret;    if (krb5_checksum_is_keyed(context, cktype) == FALSE) {	krb5_set_error_string(context, "PAC checksum type is not keyed");	return EINVAL;    }    ret = krb5_checksumsize(context, cktype, cksumsize);    if (ret)	return ret;        *cksumtype = (uint32_t)cktype;    return 0;}krb5_error_code_krb5_pac_sign(krb5_context context,	       krb5_pac p,	       time_t authtime,	       krb5_principal principal,	       const krb5_keyblock *server_key,	       const krb5_keyblock *priv_key,	       krb5_data *data){    krb5_error_code ret;    krb5_storage *sp = NULL, *spdata = NULL;    uint32_t end;    size_t server_size, priv_size;    uint32_t server_offset = 0, priv_offset = 0;    uint32_t server_cksumtype = 0, priv_cksumtype = 0;    int i, num = 0;    krb5_data logon, d;    krb5_data_zero(&logon);    if (p->logon_name == NULL)	num++;    if (p->server_checksum == NULL)	num++;    if (p->privsvr_checksum == NULL)	num++;    if (num) {	void *ptr;	ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (p->pac->numbuffers + num - 1)));	if (ptr == NULL) {	    krb5_set_error_string(context, "out of memory");	    return ENOMEM;	}	p->pac = ptr;	if (p->logon_name == NULL) {	    p->logon_name = &p->pac->buffers[p->pac->numbuffers++];	    memset(p->logon_name, 0, sizeof(*p->logon_name));	    p->logon_name->type = PAC_LOGON_NAME;	}	if (p->server_checksum == NULL) {	    p->server_checksum = &p->pac->buffers[p->pac->numbuffers++];	    memset(p->server_checksum, 0, sizeof(*p->server_checksum));	    p->server_checksum->type = PAC_SERVER_CHECKSUM;	}	if (p->privsvr_checksum == NULL) {	    p->privsvr_checksum = &p->pac->buffers[p->pac->numbuffers++];	    memset(p->privsvr_checksum, 0, sizeof(*p->privsvr_checksum));	    p->privsvr_checksum->type = PAC_PRIVSVR_CHECKSUM;	}    }    /* Calculate LOGON NAME */    ret = build_logon_name(context, authtime, principal, &logon);    if (ret)	goto out;    /* Set lengths for checksum */    ret = pac_checksum(context, server_key, &server_cksumtype, &server_size);    if (ret)	goto out;    ret = pac_checksum(context, priv_key, &priv_cksumtype, &priv_size);    if (ret)	goto out;    /* Encode PAC */    sp = krb5_storage_emem();    if (sp == NULL) {	krb5_set_error_string(context, "out of memory");	return ENOMEM;    }    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);    spdata = krb5_storage_emem();    if (spdata == NULL) {	krb5_storage_free(sp);	krb5_set_error_string(context, "out of memory");	return ENOMEM;    }    krb5_storage_set_flags(spdata, KRB5_STORAGE_BYTEORDER_LE);    CHECK(ret, krb5_store_uint32(sp, p->pac->numbuffers), out);    CHECK(ret, krb5_store_uint32(sp, p->pac->version), out);    end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers);    for (i = 0; i < p->pac->numbuffers; i++) {	uint32_t len;	size_t sret;	void *ptr = NULL;	/* store data */	if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) {	    len = server_size + 4;	    server_offset = end + 4;	    CHECK(ret, krb5_store_uint32(spdata, server_cksumtype), out);	    CHECK(ret, fill_zeros(context, spdata, server_size), out);	} else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) {	    len = priv_size + 4;	    priv_offset = end + 4;	    CHECK(ret, krb5_store_uint32(spdata, priv_cksumtype), out);	    CHECK(ret, fill_zeros(context, spdata, priv_size), out);	} else if (p->pac->buffers[i].type == PAC_LOGON_NAME) {	    len = krb5_storage_write(spdata, logon.data, logon.length);	    if (logon.length != len) {		ret = EINVAL;		goto out;	    }	} else {	    len = p->pac->buffers[i].buffersize;	    ptr = (char *)p->data.data + p->pac->buffers[i].offset_lo;	    sret = krb5_storage_write(spdata, ptr, len);	    if (sret != len) {		krb5_set_error_string(context, "out of memory");		ret = ENOMEM;		goto out;	    }	    /* XXX if not aligned, fill_zeros */	}	/* write header */	CHECK(ret, krb5_store_uint32(sp, p->pac->buffers[i].type), out);	CHECK(ret, krb5_store_uint32(sp, len), out);	CHECK(ret, krb5_store_uint32(sp, end), out);	CHECK(ret, krb5_store_uint32(sp, 0), out);	/* advance data endpointer and align */	{	    int32_t e;	    end += len;	    e = ((end + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT;	    if (end != e) {		CHECK(ret, fill_zeros(context, spdata, e - end), out);	    }	    end = e;	}    }    /* assert (server_offset != 0 && priv_offset != 0); */    /* export PAC */    ret = krb5_storage_to_data(spdata, &d);    if (ret) {	krb5_set_error_string(context, "out of memory");	goto out;    }    ret = krb5_storage_write(sp, d.data, d.length);    if (ret != d.length) {	krb5_data_free(&d);	krb5_set_error_string(context, "out of memory");	ret = ENOMEM;	goto out;    }    krb5_data_free(&d);    ret = krb5_storage_to_data(sp, &d);    if (ret) {	krb5_set_error_string(context, "out of memory");	goto out;    }    /* sign */    ret = create_checksum(context, server_key,			  d.data, d.length,			  (char *)d.data + server_offset, server_size);    if (ret) {	krb5_data_free(&d);	goto out;    }    ret = create_checksum(context, priv_key,			  (char *)d.data + server_offset, server_size,			  (char *)d.data + priv_offset, priv_size);    if (ret) {	krb5_data_free(&d);	goto out;    }    /* done */    *data = d;    krb5_data_free(&logon);    krb5_storage_free(sp);    krb5_storage_free(spdata);    return 0;out:    krb5_data_free(&logon);    if (sp)	krb5_storage_free(sp);    if (spdata)	krb5_storage_free(spdata);    return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -