/*
*/
/*
*
* Copyright 2008 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
* require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
*
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original M.I.T. software.
* M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
*
*/
#include "k5-int.h"
#include "k5-utf8.h"
/* draft-brezak-win2k-krb-authz-00 */
/*
* A PAC consists of a sequence of PAC_INFO_BUFFERs, preceeded by
* a PACTYPE header. Decoding the contents of the buffers is left
* to the application (notwithstanding signature verification).
*/
/*
* SUNW17PACresync
* These should eventually go to k5-platform.h or equiv.
*/
static inline unsigned short
{
const unsigned char *p = cvp;
return GET(16,p);
return GETSWAPPED(16,p);
#else
return (p[0] | (p[1] << 8));
#endif
}
static inline unsigned int
{
const unsigned char *p = cvp;
return GET(32,p);
return GETSWAPPED(32,p);
#else
return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
#endif
}
static inline UINT64_TYPE
{
const unsigned char *p = cvp;
return GET(64,p);
return GETSWAPPED(64,p);
#else
#endif
}
static inline void
{
unsigned char *p = vp;
#else
p[0] = (val ) & 0xff;
#endif
}
static inline void
{
unsigned char *p = vp;
#else
p[0] = (val ) & 0xff;
#endif
}
static inline void
{
unsigned char *p = vp;
#else
p[0] = (unsigned char)((val ) & 0xff);
#endif
}
typedef struct _PAC_INFO_BUFFER {
/* ulType */
typedef struct _PACTYPE {
} PACTYPE;
struct krb5_pac_data {
};
static krb5_error_code
/*
* Add a buffer to the provided PAC and update header.
*/
static krb5_error_code
{
char *pac_data;
/* Check there isn't already a buffer of this type */
/* Solaris Kerberos */
"Duplicate PAC buffer of type %d",
type);
return EINVAL;
}
sizeof(PACTYPE) +
return ENOMEM;
}
return ENOMEM;
}
/* Update offsets of existing buffers */
/* Make room for new PAC_INFO_BUFFER */
/* Initialise new PAC_INFO_BUFFER */
/* Copy in new PAC data and zero padding bytes */
if (zerofill)
else
}
return 0;
}
{
}
/*
* Free a PAC
*/
void KRB5_CALLCONV
{
}
}
}
static krb5_error_code
{
size_t i;
/* Solaris Kerberos */
"Invalid argument 'pac' is NULL");
return EINVAL;
}
else {
/* Solaris Kerberos */
"Invalid buffer found looping thru PAC buffers (type=%d, i=%d)",
type, i);
return EINVAL;
}
}
}
/* Solaris Kerberos */
"No PAC buffer found (type=%d)",
type);
return ENOENT;
}
}
return 0;
}
/*
* Find a buffer and copy data into output
*/
{
krb5_data d;
if (ret != 0)
return ret;
return ENOMEM;
return 0;
}
/*
* Return an array of the types of data in the PAC
*/
{
size_t i;
return ENOMEM;
return 0;
}
/*
* Initialize PAC
*/
{
return ENOMEM;
return ENOMEM;
}
return ENOMEM;
}
return 0;
}
/*
* Parse the supplied data into the PAC allocated by this function
*/
const void *ptr,
{
size_t i;
const unsigned char *p = (const unsigned char *)ptr;
if (len < PACTYPE_LENGTH) {
/* Solaris Kerberos */
"PAC type length is out of range (len=%d)",
len);
return ERANGE;
}
cbuffers = load_32_le(p);
p += 4;
version = load_32_le(p);
p += 4;
if (version != 0) {
/* Solaris Kerberos */
"Invalid PAC version is %d, should be 0",
version);
return EINVAL;
}
if (len < header_len) {
/* Solaris Kerberos */
"PAC header len (%d) out of range",
len);
return ERANGE;
}
if (ret != 0)
return ret;
return ENOMEM;
}
p += 4;
p += 4;
p += 8;
/* Solaris Kerberos */
"PAC buffer offset mis-aligned");
return EINVAL;
}
/* Solaris Kerberos */
"PAC offset is out of range");
return ERANGE;
}
}
return ENOMEM;
}
return 0;
}
static krb5_error_code
k5_time_to_seconds_since_1970(krb5_context context, krb5_int64 ntTime, krb5_timestamp *elapsedSeconds)
{
ntTime /= 10000000;
if (abstime > KRB5_INT32_MAX) {
return ERANGE;
}
return 0;
}
static krb5_error_code
{
*ntTime = elapsedSeconds;
if (elapsedSeconds > 0)
*ntTime += NT_TIME_EPOCH;
*ntTime *= 10000000;
return 0;
}
static krb5_error_code
{
char *pac_princname;
unsigned char *p;
if (ret != 0)
return ret;
/* Solaris Kerberos */
"PAC client info length out of range",
return ERANGE;
}
p = (unsigned char *)client_info.data;
pac_nt_authtime = load_64_le(p);
p += 8;
p += 2;
if (ret != 0)
return ret;
pac_princname_length % 2) {
/* Solaris Kerberos */
"PAC client info length is out of range");
return ERANGE;
}
if (ret != 0)
return ret;
if (ret != 0) {
return ret;
}
if (pac_authtime != authtime) {
/* Solaris Kerberos */
/* Need better ret code here but don't see one */
sizeof (timestring), &fill);
sizeof (pac_timestring), &fill);
"PAC verify fail: PAC authtime '%s' does not match authtime '%s'. PAC principal is '%s'",
}
/* Solaris Kerberos */
if (pac_princname && !perr) {
"Wrong principal in request: PAC verify: Principal in PAC is '%s' and does not match '%s'",
}
if (p_name)
}
return ret;
}
static krb5_error_code
{
size_t i;
break;
}
}
/* Solaris Kerberos */
"No PAC buffer found (type=%d)",
type);
return ENOENT;
}
return ERANGE;
}
return KRB5_BAD_MSIZE;
}
/* Zero out the data portion of the checksum only */
0,
return 0;
}
static krb5_error_code
const krb5_keyblock *server)
{
krb5_octet *p;
if (ret != 0)
return ret;
return KRB5_BAD_MSIZE;
}
return ENOMEM;
/* Zero out both checksum buffers */
if (ret != 0) {
return ret;
}
if (ret != 0) {
return ret;
}
if (ret != 0) {
return ret;
}
/* Solaris Kerberos */
"Decrypt integrity check failed for PAC");
}
return ret;
}
static krb5_error_code
const krb5_keyblock *privsvr)
{
krb5_octet *p;
if (ret != 0)
return ret;
return KRB5_BAD_MSIZE;
}
if (ret != 0)
return ret;
return KRB5_BAD_MSIZE;
}
if (ret != 0)
return ret;
/* Solaris Kerberos */
"Decrypt integrity check failed for PAC");
}
return ret;
}
const krb5_keyblock *server,
const krb5_keyblock *privsvr)
{
return EINVAL;
}
if (ret != 0)
return ret;
if (ret != 0)
return ret;
}
if (ret != 0)
return ret;
}
return 0;
}
static krb5_error_code
{
/* If we already have a CLIENT_INFO buffer, then just validate it */
}
if (ret != 0)
goto cleanup;
if (ret != 0)
goto cleanup;
if (ret != 0)
goto cleanup;
p = (unsigned char *)client_info.data;
/* copy in authtime converted to a 64-bit NT time */
store_64_le(nt_authtime, p);
p += 8;
/* copy in number of UCS-2 characters in principal name */
p += 2;
/* copy in principal name */
if (princ_name_utf8 != NULL)
if (princ_name_ucs2 != NULL)
return ret;
}
static krb5_error_code
const krb5_keyblock *key,
{
if (ret != 0)
return ret;
if (ret != 0)
return ret;
if (ret == 0) {
/* If we're resigning PAC, make sure we can fit checksum into existing buffer */
return ERANGE;
}
} else {
/* Add a zero filled buffer */
if (ret != 0)
return ret;
}
/* Encode checksum type into buffer */
return 0;
}
/* in-place encoding of PAC header */
static krb5_error_code
{
size_t i;
unsigned char *p;
p += 4;
p += 4;
p += 4;
p += 4;
p += 8;
return ERANGE;
}
}
return 0;
}
#if 0
/*
* SUNW17PACresync
* We don't have the new MIT iov interfaces yet and don't need them yet.
* We'll need this for full 1.7 resync.
*/
const krb5_keyblock *server_key,
const krb5_keyblock *privsvr_key,
{
if (ret != 0)
return ret;
}
/* Create zeroed buffers for both checksums */
if (ret != 0)
return ret;
if (ret != 0)
return ret;
/* Now, encode the PAC header so that the checksums will include it */
if (ret != 0)
return ret;
/* Generate the server checksum over the entire PAC */
if (ret != 0)
return ret;
if (ret != 0)
return ret;
/* Generate the privsvr checksum over the server checksum buffer */
if (ret != 0)
return ret;
if (ret != 0)
return ret;
return ENOMEM;
return 0;
}
#endif