--- /dev/null
+/*-
+ * Copyright (c) 2003, 2005 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#include <asn_internal.h>
+#include <asn_codecs_prim.h>
+#include <BOOLEAN.h>
+
+/*
+ * BOOLEAN basic type description.
+ */
+static ber_tlv_tag_t asn_DEF_BOOLEAN_tags[] = {
+ (ASN_TAG_CLASS_UNIVERSAL | (1 << 2))
+};
+asn_TYPE_descriptor_t asn_DEF_BOOLEAN = {
+ "BOOLEAN",
+ "BOOLEAN",
+ BOOLEAN_free,
+ BOOLEAN_print,
+ asn_generic_no_constraint,
+ BOOLEAN_decode_ber,
+ BOOLEAN_encode_der,
+ BOOLEAN_decode_xer,
+ BOOLEAN_encode_xer,
+ BOOLEAN_decode_uper, /* Unaligned PER decoder */
+ BOOLEAN_encode_uper, /* Unaligned PER encoder */
+ 0, /* Use generic outmost tag fetcher */
+ asn_DEF_BOOLEAN_tags,
+ sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
+ asn_DEF_BOOLEAN_tags, /* Same as above */
+ sizeof(asn_DEF_BOOLEAN_tags) / sizeof(asn_DEF_BOOLEAN_tags[0]),
+ 0, /* No PER visible constraints */
+ 0, 0, /* No members */
+ 0 /* No specifics */
+};
+
+/*
+ * Decode BOOLEAN type.
+ */
+asn_dec_rval_t
+BOOLEAN_decode_ber(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td,
+ void **bool_value, const void *buf_ptr, size_t size,
+ int tag_mode) {
+ BOOLEAN_t *st = (BOOLEAN_t *)*bool_value;
+ asn_dec_rval_t rval;
+ ber_tlv_len_t length;
+ ber_tlv_len_t lidx;
+
+ if(st == NULL) {
+ st = (BOOLEAN_t *)(*bool_value = CALLOC(1, sizeof(*st)));
+ if(st == NULL) {
+ rval.code = RC_FAIL;
+ rval.consumed = 0;
+ return rval;
+ }
+ }
+
+ ASN_DEBUG("Decoding %s as BOOLEAN (tm=%d)",
+ td->name, tag_mode);
+
+ /*
+ * Check tags.
+ */
+ rval = ber_check_tags(opt_codec_ctx, td, 0, buf_ptr, size,
+ tag_mode, 0, &length, 0);
+ if(rval.code != RC_OK)
+ return rval;
+
+ ASN_DEBUG("Boolean length is %d bytes", (int)length);
+
+ buf_ptr = ((const char *)buf_ptr) + rval.consumed;
+ size -= rval.consumed;
+ if(length > (ber_tlv_len_t)size) {
+ rval.code = RC_WMORE;
+ rval.consumed = 0;
+ return rval;
+ }
+
+ /*
+ * Compute boolean value.
+ */
+ for(*st = 0, lidx = 0;
+ (lidx < length) && *st == 0; lidx++) {
+ /*
+ * Very simple approach: read bytes until the end or
+ * value is already TRUE.
+ * BOOLEAN is not supposed to contain meaningful data anyway.
+ */
+ *st |= ((const uint8_t *)buf_ptr)[lidx];
+ }
+
+ rval.code = RC_OK;
+ rval.consumed += length;
+
+ ASN_DEBUG("Took %ld/%ld bytes to encode %s, value=%d",
+ (long)rval.consumed, (long)length,
+ td->name, *st);
+
+ return rval;
+}
+
+asn_enc_rval_t
+BOOLEAN_encode_der(asn_TYPE_descriptor_t *td, void *sptr,
+ int tag_mode, ber_tlv_tag_t tag,
+ asn_app_consume_bytes_f *cb, void *app_key) {
+ asn_enc_rval_t erval;
+ BOOLEAN_t *st = (BOOLEAN_t *)sptr;
+
+ erval.encoded = der_write_tags(td, 1, tag_mode, 0, tag, cb, app_key);
+ if(erval.encoded == -1) {
+ erval.failed_type = td;
+ erval.structure_ptr = sptr;
+ return erval;
+ }
+
+ if(cb) {
+ uint8_t bool_value;
+
+ bool_value = *st ? 0xff : 0; /* 0xff mandated by DER */
+
+ if(cb(&bool_value, 1, app_key) < 0) {
+ erval.encoded = -1;
+ erval.failed_type = td;
+ erval.structure_ptr = sptr;
+ return erval;
+ }
+ }
+
+ erval.encoded += 1;
+
+ _ASN_ENCODED_OK(erval);
+}
+
+
+/*
+ * Decode the chunk of XML text encoding INTEGER.
+ */
+static enum xer_pbd_rval
+BOOLEAN__xer_body_decode(asn_TYPE_descriptor_t *td, void *sptr, const void *chunk_buf, size_t chunk_size) {
+ BOOLEAN_t *st = (BOOLEAN_t *)sptr;
+ const char *p = (const char *)chunk_buf;
+
+ (void)td;
+
+ if(chunk_size && p[0] == 0x3c /* '<' */) {
+ switch(xer_check_tag(chunk_buf, chunk_size, "false")) {
+ case XCT_BOTH:
+ /* "<false/>" */
+ *st = 0;
+ break;
+ case XCT_UNKNOWN_BO:
+ if(xer_check_tag(chunk_buf, chunk_size, "true")
+ != XCT_BOTH)
+ return XPBD_BROKEN_ENCODING;
+ /* "<true/>" */
+ *st = 1; /* Or 0xff as in DER?.. */
+ break;
+ default:
+ return XPBD_BROKEN_ENCODING;
+ }
+ return XPBD_BODY_CONSUMED;
+ } else {
+ return XPBD_BROKEN_ENCODING;
+ }
+}
+
+
+asn_dec_rval_t
+BOOLEAN_decode_xer(asn_codec_ctx_t *opt_codec_ctx,
+ asn_TYPE_descriptor_t *td, void **sptr, const char *opt_mname,
+ const void *buf_ptr, size_t size) {
+
+ return xer_decode_primitive(opt_codec_ctx, td,
+ sptr, sizeof(BOOLEAN_t), opt_mname, buf_ptr, size,
+ BOOLEAN__xer_body_decode);
+}
+
+asn_enc_rval_t
+BOOLEAN_encode_xer(asn_TYPE_descriptor_t *td, void *sptr,
+ int ilevel, enum xer_encoder_flags_e flags,
+ asn_app_consume_bytes_f *cb, void *app_key) {
+ const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
+ asn_enc_rval_t er;
+
+ (void)ilevel;
+ (void)flags;
+
+ if(!st) _ASN_ENCODE_FAILED;
+
+ if(*st) {
+ _ASN_CALLBACK("<true/>", 7);
+ er.encoded = 7;
+ } else {
+ _ASN_CALLBACK("<false/>", 8);
+ er.encoded = 8;
+ }
+
+ _ASN_ENCODED_OK(er);
+cb_failed:
+ _ASN_ENCODE_FAILED;
+}
+
+int
+BOOLEAN_print(asn_TYPE_descriptor_t *td, const void *sptr, int ilevel,
+ asn_app_consume_bytes_f *cb, void *app_key) {
+ const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
+ const char *buf;
+ size_t buflen;
+
+ (void)td; /* Unused argument */
+ (void)ilevel; /* Unused argument */
+
+ if(st) {
+ if(*st) {
+ buf = "TRUE";
+ buflen = 4;
+ } else {
+ buf = "FALSE";
+ buflen = 5;
+ }
+ } else {
+ buf = "<absent>";
+ buflen = 8;
+ }
+
+ return (cb(buf, buflen, app_key) < 0) ? -1 : 0;
+}
+
+void
+BOOLEAN_free(asn_TYPE_descriptor_t *td, void *ptr, int contents_only) {
+ if(td && ptr && !contents_only) {
+ FREEMEM(ptr);
+ }
+}
+
+asn_dec_rval_t
+BOOLEAN_decode_uper(asn_codec_ctx_t *opt_codec_ctx, asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void **sptr, asn_per_data_t *pd) {
+ asn_dec_rval_t rv;
+ BOOLEAN_t *st = (BOOLEAN_t *)*sptr;
+
+ (void)opt_codec_ctx;
+ (void)constraints;
+
+ if(!st) {
+ st = (BOOLEAN_t *)(*sptr = MALLOC(sizeof(*st)));
+ if(!st) _ASN_DECODE_FAILED;
+ }
+
+ /*
+ * Extract a single bit
+ */
+ switch(per_get_few_bits(pd, 1)) {
+ case 1: *st = 1; break;
+ case 0: *st = 0; break;
+ case -1: default: _ASN_DECODE_STARVED;
+ }
+
+ ASN_DEBUG("%s decoded as %s", td->name, *st ? "TRUE" : "FALSE");
+
+ rv.code = RC_OK;
+ rv.consumed = 1;
+ return rv;
+}
+
+
+asn_enc_rval_t
+BOOLEAN_encode_uper(asn_TYPE_descriptor_t *td,
+ asn_per_constraints_t *constraints, void *sptr, asn_per_outp_t *po) {
+ const BOOLEAN_t *st = (const BOOLEAN_t *)sptr;
+ asn_enc_rval_t er = { 0, 0, 0 };
+
+ (void)constraints;
+
+ if(!st) _ASN_ENCODE_FAILED;
+
+ if(per_put_few_bits(po, *st ? 1 : 0, 1))
+ _ASN_ENCODE_FAILED;
+
+ _ASN_ENCODED_OK(er);
+}
--- /dev/null
+/*-
+ * Copyright (c) 2003 Lev Walkin <vlm@lionet.info>. All rights reserved.
+ * Redistribution and modifications are permitted subject to BSD license.
+ */
+#ifndef _BOOLEAN_H_
+#define _BOOLEAN_H_
+
+#include <asn_application.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The underlying integer may contain various values, but everything
+ * non-zero is capped to 0xff by the DER encoder. The BER decoder may
+ * yield non-zero values different from 1, beware.
+ */
+typedef int BOOLEAN_t;
+
+extern asn_TYPE_descriptor_t asn_DEF_BOOLEAN;
+
+asn_struct_free_f BOOLEAN_free;
+asn_struct_print_f BOOLEAN_print;
+ber_type_decoder_f BOOLEAN_decode_ber;
+der_type_encoder_f BOOLEAN_encode_der;
+xer_type_decoder_f BOOLEAN_decode_xer;
+xer_type_encoder_f BOOLEAN_encode_xer;
+per_type_decoder_f BOOLEAN_decode_uper;
+per_type_encoder_f BOOLEAN_encode_uper;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _BOOLEAN_H_ */
#include "GSSSessionData.h"
static asn_TYPE_member_t asn_MBR_GSSSessionData_1[] = {
- { ATF_NOFLAGS, 0, offsetof(struct GSSSessionData, expiration),
+ { ATF_NOFLAGS, 0, offsetof(struct GSSSessionData, established),
(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
+1, /* EXPLICIT tag at current level */
+ &asn_DEF_BOOLEAN,
+ 0, /* Defer constraints checking to the member type */
+ 0, /* PER is not compiled, use -gen-PER */
+ 0,
+ "established"
+ },
+ { ATF_NOFLAGS, 0, offsetof(struct GSSSessionData, delegated),
+ (ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+ +1, /* EXPLICIT tag at current level */
+ &asn_DEF_BOOLEAN,
+ 0, /* Defer constraints checking to the member type */
+ 0, /* PER is not compiled, use -gen-PER */
+ 0,
+ "delegated"
+ },
+ { ATF_NOFLAGS, 0, offsetof(struct GSSSessionData, expiration),
+ (ASN_TAG_CLASS_CONTEXT | (2 << 2)),
+ +1, /* EXPLICIT tag at current level */
&asn_DEF_Uint32,
0, /* Defer constraints checking to the member type */
0, /* PER is not compiled, use -gen-PER */
"expiration"
},
{ ATF_NOFLAGS, 0, offsetof(struct GSSSessionData, username),
- (ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+ (ASN_TAG_CLASS_CONTEXT | (3 << 2)),
+1, /* EXPLICIT tag at current level */
&asn_DEF_OCTET_STRING,
0, /* Defer constraints checking to the member type */
"username"
},
{ ATF_NOFLAGS, 0, offsetof(struct GSSSessionData, gssname),
- (ASN_TAG_CLASS_CONTEXT | (2 << 2)),
+ (ASN_TAG_CLASS_CONTEXT | (4 << 2)),
+1, /* EXPLICIT tag at current level */
&asn_DEF_OCTET_STRING,
0, /* Defer constraints checking to the member type */
(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
};
static asn_TYPE_tag2member_t asn_MAP_GSSSessionData_tag2el_1[] = {
- { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* expiration */
- { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* username */
- { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 } /* gssname */
+ { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* established */
+ { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* delegated */
+ { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 }, /* expiration */
+ { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 3, 0, 0 }, /* username */
+ { (ASN_TAG_CLASS_CONTEXT | (4 << 2)), 4, 0, 0 } /* gssname */
};
static asn_SEQUENCE_specifics_t asn_SPC_GSSSessionData_specs_1 = {
sizeof(struct GSSSessionData),
offsetof(struct GSSSessionData, _asn_ctx),
asn_MAP_GSSSessionData_tag2el_1,
- 3, /* Count of tags in the map */
+ 5, /* Count of tags in the map */
0, 0, 0, /* Optional elements (not needed) */
-1, /* Start extensions */
-1 /* Stop extensions */
/sizeof(asn_DEF_GSSSessionData_tags_1[0]), /* 1 */
0, /* No PER visible constraints */
asn_MBR_GSSSessionData_1,
- 3, /* Elements count */
+ 5, /* Elements count */
&asn_SPC_GSSSessionData_specs_1 /* Additional specs */
};
#include <asn_application.h>
/* Including external dependencies */
+#include <BOOLEAN.h>
#include "Uint32.h"
#include <OCTET_STRING.h>
#include <constr_SEQUENCE.h>
/* GSSSessionData */
typedef struct GSSSessionData {
+ BOOLEAN_t established;
+ BOOLEAN_t delegated;
Uint32_t expiration;
OCTET_STRING_t username;
OCTET_STRING_t gssname;
ber_tlv_length.c \
ber_tlv_tag.c \
BIT_STRING.c \
+ BOOLEAN.c \
constraints.c \
constr_SEQUENCE.c \
constr_TYPE.c \
ber_tlv_length.h \
ber_tlv_tag.h \
BIT_STRING.h \
+ BOOLEAN.h \
constraints.h \
constr_SEQUENCE.h \
constr_TYPE.h \
Uint32 ::= INTEGER (0..4294967295)
GSSSessionData ::= SEQUENCE {
- expiration [0] Uint32,
- username [1] OCTET STRING,
- gssname [2] OCTET STRING
+ established [0] BOOLEAN,
+ delegated [1] BOOLEAN,
+ expiration [2] Uint32,
+ username [3] OCTET STRING,
+ gssname [4] OCTET STRING
}
END
return escaped;
}
-static void mag_store_deleg_creds(request_rec *req,
- char *dir, char *clientname,
- gss_cred_id_t delegated_cred,
- char **ccachefile)
+static char *mag_gss_name_to_ccache_name(request_rec *req,
+ char *dir, const char *gss_name)
{
- gss_key_value_element_desc element;
- gss_key_value_set_desc store;
- char *value;
- uint32_t maj, min;
char *escaped;
/* We need to escape away '/', we can't have path separators in
* a ccache file name */
/* first double escape the esacping char (~) if any */
- escaped = escape(req->pool, clientname, '~', "~~");
- if (!escaped) return;
+ escaped = escape(req->pool, gss_name, '~', "~~");
/* then escape away the separator (/) if any */
escaped = escape(req->pool, escaped, '/', "~");
- if (!escaped) return;
- value = apr_psprintf(req->pool, "FILE:%s/%s", dir, escaped);
+ return apr_psprintf(req->pool, "%s/%s", dir, escaped);
+}
+
+static void mag_set_KRB5CCANME(request_rec *req, char *ccname)
+{
+ apr_status_t status;
+ apr_finfo_t finfo;
+ char *value;
+ status = apr_stat(&finfo, ccname, APR_FINFO_MIN, req->pool);
+ if (status != APR_SUCCESS && status != APR_INCOMPLETE) {
+ /* set the file cache anyway, but warn */
+ ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req,
+ "KRB5CCNAME file (%s) lookup failed!", ccname);
+ }
+
+ value = apr_psprintf(req->pool, "FILE:%s", ccname);
+ apr_table_set(req->subprocess_env, "KRB5CCNAME", value);
+}
+
+static void mag_store_deleg_creds(request_rec *req,
+ char *dir, char *clientname,
+ gss_cred_id_t delegated_cred,
+ char **ccachefile)
+{
+ gss_key_value_element_desc element;
+ gss_key_value_set_desc store;
+ char *ccname;
+ uint32_t maj, min;
element.key = "ccache";
- element.value = value;
store.elements = &element;
store.count = 1;
+ ccname = mag_gss_name_to_ccache_name(req, dir, clientname);
+ element.value = apr_psprintf(req->pool, "FILE:%s", ccname);
+
maj = gss_store_cred_into(&min, delegated_cred, GSS_C_INITIATE,
GSS_C_NULL_OID, 1, 1, &store, NULL, NULL);
if (GSS_ERROR(maj)) {
maj, min));
}
- *ccachefile = value;
+ *ccachefile = ccname;
}
#endif
req->ap_auth_type = apr_pstrdup(req->pool,
auth_types[mc->auth_type]);
req->user = apr_pstrdup(req->pool, mc->user_name);
+ if (cfg->deleg_ccache_dir && mc->delegated) {
+ char *ccname;
+ ccname = mag_gss_name_to_ccache_name(req,
+ cfg->deleg_ccache_dir,
+ mc->gss_name);
+ if (ccname) {
+ mag_set_KRB5CCANME(req, ccname);
+ }
+ }
ret = OK;
goto done;
}
delegated_cred, &ccachefile);
if (ccachefile) {
- apr_table_set(req->subprocess_env, "KRB5CCNAME", ccachefile);
+ mag_set_KRB5CCANME(req, ccachefile);
+ }
+
+ if (mc) {
+ mc->delegated = true;
}
}
#endif
const char *gss_name;
time_t expiration;
int auth_type;
+ bool delegated;
};
#define discard_const(ptr) ((void *)((uintptr_t)(ptr)))
return;
}
+ /* booleans */
+ if (gsessdata->established != 0) mc->established = true;
+ if (gsessdata->delegated != 0) mc->delegated = true;
+
/* get time */
expiration = gsessdata->expiration;
if (expiration < time(NULL)) {
}
}
+ gsessdata.established = mc->established?1:0;
+ gsessdata.delegated = mc->delegated?1:0;
gsessdata.expiration = mc->expiration;
if (OCTET_STRING_fromString(&gsessdata.username, mc->user_name) != 0)
goto done;