diff options
Diffstat (limited to 'source4')
264 files changed, 25771 insertions, 10833 deletions
diff --git a/source4/auth/credentials/credentials_krb5.h b/source4/auth/credentials/credentials_krb5.h index 2bd38af5c7..22c0f5abfe 100644 --- a/source4/auth/credentials/credentials_krb5.h +++ b/source4/auth/credentials/credentials_krb5.h @@ -21,9 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -struct EncryptionKey; - -#include "heimdal/lib/gssapi/gssapi.h" +#include "heimdal/lib/gssapi/gssapi/gssapi.h" struct ccache_container; diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index ed407b623b..136962d892 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -24,7 +24,7 @@ #include "includes.h" #include "system/kerberos.h" -#include "heimdal/lib/gssapi/gssapi.h" +#include "heimdal/lib/gssapi/gssapi/gssapi.h" #include "auth/kerberos/kerberos.h" #include "librpc/gen_ndr/krb5pac.h" #include "auth/auth.h" @@ -73,6 +73,7 @@ struct gensec_gssapi_state { * layer... */ size_t max_wrap_buf_size; + int gss_exchange_count; }; static size_t gensec_gssapi_max_input_size(struct gensec_security *gensec_security); @@ -133,12 +134,14 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security) { struct gensec_gssapi_state *gensec_gssapi_state; krb5_error_code ret; - + struct gsskrb5_send_to_kdc send_to_kdc; + gensec_gssapi_state = talloc(gensec_security, struct gensec_gssapi_state); if (!gensec_gssapi_state) { return NT_STATUS_NO_MEMORY; } + gensec_gssapi_state->gss_exchange_count = 0; gensec_gssapi_state->max_wrap_buf_size = lp_parm_int(-1, "gensec_gssapi", "max wrap buf size", 65536); @@ -186,10 +189,18 @@ static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security) gensec_gssapi_state->gss_oid = gss_mech_krb5; + send_to_kdc.func = smb_krb5_send_and_recv_func; + send_to_kdc.ptr = gensec_security->event_ctx; + + ret = gsskrb5_set_send_to_kdc(&send_to_kdc); + if (ret) { + DEBUG(1,("gensec_krb5_start: gsskrb5_set_send_to_kdc failed\n")); + return NT_STATUS_INTERNAL_ERROR; + } ret = smb_krb5_init_context(gensec_gssapi_state, &gensec_gssapi_state->smb_krb5_context); if (ret) { - DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n", + DEBUG(1,("gensec_krb5_start: krb5_init_context failed (%s)\n", error_message(ret))); return NT_STATUS_INTERNAL_ERROR; } @@ -431,6 +442,8 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, } + gensec_gssapi_state->gss_exchange_count++; + if (maj_stat == GSS_S_COMPLETE) { *out = data_blob_talloc(out_mem_ctx, output_token.value, output_token.length); gss_release_buffer(&min_stat2, &output_token); @@ -493,12 +506,14 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, /* garbage input, possibly from the auto-mech detection */ return NT_STATUS_INVALID_PARAMETER; default: - DEBUG(1, ("GSS(krb5) Update failed: %s\n", + DEBUG(1, ("GSS Update(krb5)(%d) Update failed: %s\n", + gensec_gssapi_state->gss_exchange_count, gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); return nt_status; } } else { - DEBUG(1, ("GSS Update failed: %s\n", + DEBUG(1, ("GSS Update(%d) failed: %s\n", + gensec_gssapi_state->gss_exchange_count, gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); return nt_status; } @@ -583,7 +598,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, &conf_state, &output_token); if (GSS_ERROR(maj_stat)) { - DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n", + DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); return NT_STATUS_ACCESS_DENIED; } @@ -648,7 +663,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, &conf_state, &output_token); if (GSS_ERROR(maj_stat)) { - DEBUG(1, ("gensec_gssapi_wrap: GSS Wrap failed: %s\n", + DEBUG(1, ("GSS Update(SSF_NEG): GSS Wrap failed: %s\n", gssapi_error_string(out_mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); return NT_STATUS_ACCESS_DENIED; } @@ -1185,38 +1200,57 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi return NT_STATUS_NO_MEMORY; } - maj_stat = gss_krb5_copy_service_keyblock(&min_stat, - gensec_gssapi_state->gssapi_context, - &keyblock); - - if (maj_stat == 0) { - maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat, - gensec_gssapi_state->gssapi_context, - &authtime); - } - - if (maj_stat == 0) { - maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, - gensec_gssapi_state->gssapi_context, - KRB5_AUTHDATA_WIN2K_PAC, - &pac); - } - + maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat, + gensec_gssapi_state->gssapi_context, + KRB5_AUTHDATA_WIN2K_PAC, + &pac); + + if (maj_stat == 0) { pac_blob = data_blob_talloc(mem_ctx, pac.value, pac.length); gss_release_buffer(&min_stat, &pac); + + } else { + pac_blob = data_blob(NULL, 0); } /* IF we have the PAC - otherwise we need to get this * data from elsewere - local ldb, or (TODO) lookup of some * kind... */ - if (maj_stat == 0) { + if (pac_blob.length) { krb5_error_code ret; + union netr_Validation validation; - ret = krb5_parse_name(gensec_gssapi_state->smb_krb5_context->krb5_context, - principal_string, &principal); + maj_stat = gsskrb5_extract_authtime_from_sec_context(&min_stat, + gensec_gssapi_state->gssapi_context, + &authtime); + + if (GSS_ERROR(maj_stat)) { + DEBUG(1, ("gsskrb5_extract_authtime_from_sec_context: %s\n", + gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); + talloc_free(mem_ctx); + return NT_STATUS_FOOBAR; + } + + maj_stat = gsskrb5_extract_service_keyblock(&min_stat, + gensec_gssapi_state->gssapi_context, + &keyblock); + + if (GSS_ERROR(maj_stat)) { + DEBUG(1, ("gsskrb5_copy_service_keyblock failed: %s\n", + gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); + talloc_free(mem_ctx); + return NT_STATUS_FOOBAR; + } + + ret = krb5_parse_name_flags(gensec_gssapi_state->smb_krb5_context->krb5_context, + principal_string, + KRB5_PRINCIPAL_PARSE_MUST_REALM, + &principal); if (ret) { + krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, + keyblock); talloc_free(mem_ctx); return NT_STATUS_INVALID_PARAMETER; } @@ -1226,25 +1260,25 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi gensec_gssapi_state->smb_krb5_context->krb5_context, NULL, keyblock, principal, authtime, NULL); krb5_free_principal(gensec_gssapi_state->smb_krb5_context->krb5_context, principal); + krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, + keyblock); - if (NT_STATUS_IS_OK(nt_status)) { - union netr_Validation validation; - validation.sam3 = &logon_info->info3; - nt_status = make_server_info_netlogon_validation(gensec_gssapi_state, - NULL, - 3, &validation, - &server_info); - if (!NT_STATUS_IS_OK(nt_status)) { - talloc_free(mem_ctx); - return nt_status; - } - } else { - maj_stat = 1; + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return nt_status; } - } - - if (maj_stat) { - DEBUG(1, ("Unable to use PAC, resorting to local user lookup!\n")); + validation.sam3 = &logon_info->info3; + nt_status = make_server_info_netlogon_validation(gensec_gssapi_state, + NULL, + 3, &validation, + &server_info); + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return nt_status; + } + } else if (!lp_parm_bool(-1, "gensec", "require_pac", False)) { + DEBUG(1, ("Unable to find PAC, resorting to local user lookup: %s\n", + gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); nt_status = sam_get_server_info_principal(mem_ctx, principal_string, &server_info); @@ -1252,6 +1286,11 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi talloc_free(mem_ctx); return nt_status; } + } else { + DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s\n", + principal_string, + gssapi_error_string(mem_ctx, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); + return NT_STATUS_ACCESS_DENIED; } /* references the server_info into the session_info */ diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c index d84f3dedf5..66d2801520 100644 --- a/source4/auth/gensec/gensec_krb5.c +++ b/source4/auth/gensec/gensec_krb5.c @@ -527,6 +527,7 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security struct PAC_LOGON_INFO *logon_info; krb5_principal client_principal; + char *principal_string; DATA_BLOB pac; krb5_data pac_data; @@ -538,30 +539,63 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security return NT_STATUS_NO_MEMORY; } + ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal); + if (ret) { + DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n", + smb_get_krb5_error_message(context, + ret, mem_ctx))); + talloc_free(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + + ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context, + client_principal, &principal_string); + if (ret) { + DEBUG(1, ("Unable to parse client principal: %s\n", + smb_get_krb5_error_message(context, + ret, mem_ctx))); + talloc_free(mem_ctx); + return NT_STATUS_NO_MEMORY; + } + ret = krb5_ticket_get_authorization_data_type(context, gensec_krb5_state->ticket, KRB5_AUTHDATA_WIN2K_PAC, &pac_data); - if (ret) { + if (ret && lp_parm_bool(-1, "gensec", "require_pac", False)) { + DEBUG(1, ("Unable to find PAC in ticket from %s, failing to allow access: %s \n", + principal_string, + smb_get_krb5_error_message(context, + ret, mem_ctx))); + krb5_free_principal(context, client_principal); + free(principal_string); + return NT_STATUS_ACCESS_DENIED; + } else if (ret) { + /* NO pac */ DEBUG(5, ("krb5_ticket_get_authorization_data_type failed to find PAC: %s\n", smb_get_krb5_error_message(context, ret, mem_ctx))); + nt_status = sam_get_server_info_principal(mem_ctx, principal_string, + &server_info); + krb5_free_principal(context, client_principal); + free(principal_string); + + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_free(mem_ctx); + return nt_status; + } } else { + /* Found pac */ + union netr_Validation validation; + free(principal_string); + pac = data_blob_talloc(mem_ctx, pac_data.data, pac_data.length); if (!pac.data) { + krb5_free_principal(context, client_principal); talloc_free(mem_ctx); return NT_STATUS_NO_MEMORY; } - ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal); - if (ret) { - DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n", - smb_get_krb5_error_message(context, - ret, mem_ctx))); - talloc_free(mem_ctx); - return NT_STATUS_NO_MEMORY; - } - /* decode and verify the pac */ nt_status = kerberos_pac_logon_info(gensec_krb5_state, &logon_info, pac, gensec_krb5_state->smb_krb5_context->krb5_context, @@ -570,46 +604,16 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security gensec_krb5_state->ticket->ticket.authtime, NULL); krb5_free_principal(context, client_principal); - if (NT_STATUS_IS_OK(nt_status)) { - union netr_Validation validation; - validation.sam3 = &logon_info->info3; - nt_status = make_server_info_netlogon_validation(mem_ctx, - NULL, - 3, &validation, - &server_info); - } - } - - - - /* IF we have the PAC - otherwise we need to get this - * data from elsewere - local ldb, or (TODO) lookup of some - * kind... - */ - if (!NT_STATUS_IS_OK(nt_status)) { - /* NO pac, or can't parse or verify it */ - char *principal_string; - ret = krb5_ticket_get_client(context, gensec_krb5_state->ticket, &client_principal); - if (ret) { - DEBUG(5, ("krb5_ticket_get_client failed to get cleint principal: %s\n", - smb_get_krb5_error_message(context, - ret, mem_ctx))); - talloc_free(mem_ctx); - return NT_STATUS_NO_MEMORY; - } - - ret = krb5_unparse_name(gensec_krb5_state->smb_krb5_context->krb5_context, - client_principal, &principal_string); - krb5_free_principal(context, client_principal); - if (ret) { + if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); - return NT_STATUS_NO_MEMORY; + return nt_status; } - nt_status = sam_get_server_info_principal(mem_ctx, principal_string, - &server_info); - free(principal_string); - + validation.sam3 = &logon_info->info3; + nt_status = make_server_info_netlogon_validation(mem_ctx, + NULL, + 3, &validation, + &server_info); if (!NT_STATUS_IS_OK(nt_status)) { talloc_free(mem_ctx); return nt_status; diff --git a/source4/auth/kerberos/kerberos.c b/source4/auth/kerberos/kerberos.c index 06f0c186a3..2b4c5d4cb0 100644 --- a/source4/auth/kerberos/kerberos.c +++ b/source4/auth/kerberos/kerberos.c @@ -45,6 +45,8 @@ krb5_get_init_creds_opt_init(&options); + krb5_get_init_creds_opt_set_default_flags(ctx, NULL, NULL, &options); + if ((code = krb5_get_init_creds_keyblock(ctx, &my_creds, principal, keyblock, 0, NULL, &options))) { return code; @@ -87,6 +89,8 @@ krb5_get_init_creds_opt_init(&options); + krb5_get_init_creds_opt_set_default_flags(ctx, NULL, NULL, &options); + if ((code = krb5_get_init_creds_password(ctx, &my_creds, principal, password, NULL, NULL, 0, NULL, &options))) { diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c index dcfe16c896..8e1801f745 100644 --- a/source4/auth/kerberos/kerberos_pac.c +++ b/source4/auth/kerberos/kerberos_pac.c @@ -280,7 +280,8 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, return NT_STATUS_ACCESS_DENIED; } - ret = krb5_parse_name_norealm(context, logon_name->account_name, &client_principal_pac); + ret = krb5_parse_name_flags(context, logon_name->account_name, KRB5_PRINCIPAL_PARSE_NO_REALM, + &client_principal_pac); if (ret) { DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n", logon_name->account_name, @@ -591,7 +592,8 @@ static krb5_error_code make_pac_checksum(TALLOC_CTX *mem_ctx, u_LOGON_INFO->logon_info.info = LOGON_INFO; LOGON_INFO->info3 = *sam3; - ret = krb5_unparse_name_norealm(context, client_principal, &name); + ret = krb5_unparse_name_flags(context, client_principal, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name); if (ret) { return ret; } diff --git a/source4/auth/kerberos/krb5_init_context.c b/source4/auth/kerberos/krb5_init_context.c index d895d7a336..a3ef895b16 100644 --- a/source4/auth/kerberos/krb5_init_context.c +++ b/source4/auth/kerberos/krb5_init_context.c @@ -23,6 +23,7 @@ #include "includes.h" #include "system/kerberos.h" +#include "heimdal/lib/krb5/krb5_locl.h" #include "auth/kerberos/kerberos.h" #include "lib/socket/socket.h" #include "system/network.h" @@ -69,7 +70,7 @@ static void smb_krb5_debug_close(void *private) { static void smb_krb5_debug_wrapper(const char *timestr, const char *msg, void *private) { - DEBUG(3, ("Kerberos: %s\n", msg)); + DEBUG(2, ("Kerberos: %s\n", msg)); } /* @@ -224,11 +225,11 @@ static void smb_krb5_socket_handler(struct event_context *ev, struct fd_event *f } -static krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, - void *data, - krb5_krbhst_info *hi, - const krb5_data *send_buf, - krb5_data *recv_buf) +krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, + void *data, + krb5_krbhst_info *hi, + const krb5_data *send_buf, + krb5_data *recv_buf) { krb5_error_code ret; NTSTATUS status; @@ -363,13 +364,6 @@ static krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, return KRB5_KDC_UNREACH; } -/* NO internal data, so nothing to free */ -static void smb_krb5_send_and_recv_close_func(krb5_context context, void *data) -{ - return; -} - - krb5_error_code smb_krb5_init_context(void *parent_ctx, struct smb_krb5_context **smb_krb5_context) { @@ -437,9 +431,9 @@ krb5_error_code smb_krb5_init_context(void *parent_ctx, ev = event_context_find(*smb_krb5_context); /* Set use of our socket lib */ - ret = krb5_set_send_recv_func((*smb_krb5_context)->krb5_context, - smb_krb5_send_and_recv_func, - smb_krb5_send_and_recv_close_func, ev); + ret = krb5_set_send_to_kdc_func((*smb_krb5_context)->krb5_context, + smb_krb5_send_and_recv_func, + ev); if (ret) { DEBUG(1,("krb5_set_send_recv_func failed (%s)\n", smb_get_krb5_error_message((*smb_krb5_context)->krb5_context, ret, tmp_ctx))); @@ -454,12 +448,8 @@ krb5_error_code smb_krb5_init_context(void *parent_ctx, /* Set options in kerberos */ - (*smb_krb5_context)->krb5_context->fdns = FALSE; + krb5_set_dns_canonicalize_hostname((*smb_krb5_context)->krb5_context, FALSE); return 0; } - void smb_krb5_free_context(struct smb_krb5_context *smb_krb5_context) -{ - talloc_free(smb_krb5_context); -} diff --git a/source4/auth/kerberos/krb5_init_context.h b/source4/auth/kerberos/krb5_init_context.h index f3ffc067fa..7aad97e2ca 100644 --- a/source4/auth/kerberos/krb5_init_context.h +++ b/source4/auth/kerberos/krb5_init_context.h @@ -27,3 +27,8 @@ krb5_error_code smb_krb5_init_context(void *parent_ctx, struct smb_krb5_context **smb_krb5_context); void smb_krb5_free_context(struct smb_krb5_context *smb_krb5_context); +krb5_error_code smb_krb5_send_and_recv_func(krb5_context context, + void *data, + krb5_krbhst_info *hi, + const krb5_data *send_buf, + krb5_data *recv_buf); diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c index f92cf949b1..eb051a0fb2 100644 --- a/source4/dsdb/samdb/cracknames.c +++ b/source4/dsdb/samdb/cracknames.c @@ -154,8 +154,8 @@ static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_c enum drsuapi_DsNameStatus namestatus; /* parse principal */ - ret = krb5_parse_name_norealm(smb_krb5_context->krb5_context, - name, &principal); + ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, + name, KRB5_PRINCIPAL_PARSE_NO_REALM, &principal); if (ret) { DEBUG(2, ("Could not parse principal: %s: %s", name, smb_get_krb5_error_message(smb_krb5_context->krb5_context, @@ -196,7 +196,8 @@ static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_c } /* reform principal */ - ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &new_princ); + ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &new_princ); krb5_free_principal(smb_krb5_context->krb5_context, principal); @@ -231,7 +232,8 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, return WERR_OK; } - ret = krb5_parse_name_mustrealm(smb_krb5_context->krb5_context, name, &principal); + ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, name, + KRB5_PRINCIPAL_PARSE_MUST_REALM, &principal); if (ret) { info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; @@ -243,7 +245,8 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, "(&(&(|(&(dnsRoot=%s)(nETBIOSName=*))(nETBIOSName=%s))(objectclass=crossRef))(ncName=*))", ldb_binary_encode_string(mem_ctx, *realm), ldb_binary_encode_string(mem_ctx, *realm)); - ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &unparsed_name_short); + ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &unparsed_name_short); krb5_free_principal(smb_krb5_context->krb5_context, principal); if (ret) { @@ -445,11 +448,13 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, krb5_principal principal; char *unparsed_name_short; char *service; - ret = krb5_parse_name_norealm(smb_krb5_context->krb5_context, name, &principal); + ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, name, + KRB5_PRINCIPAL_PARSE_NO_REALM, &principal); if (ret) { /* perhaps it's a principal with a realm, so return the right 'domain only' response */ char **realm; - ret = krb5_parse_name_mustrealm(smb_krb5_context->krb5_context, name, &principal); + ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, name, + KRB5_PRINCIPAL_PARSE_MUST_REALM, &principal); if (ret) { info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND; return WERR_OK; @@ -473,7 +478,8 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx, domain_filter = NULL; - ret = krb5_unparse_name_norealm(smb_krb5_context->krb5_context, principal, &unparsed_name_short); + ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &unparsed_name_short); if (ret) { krb5_free_principal(smb_krb5_context->krb5_context, principal); return WERR_NOMEM; diff --git a/source4/heimdal/kdc/524.c b/source4/heimdal/kdc/524.c index d61b78d9b6..56c12efd60 100644 --- a/source4/heimdal/kdc/524.c +++ b/source4/heimdal/kdc/524.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: 524.c,v 1.37 2006/04/27 11:33:20 lha Exp $"); +RCSID("$Id: 524.c,v 1.40 2006/10/06 17:06:30 lha Exp $"); #include <krb5-v4compat.h> @@ -53,7 +53,8 @@ fetch_server (krb5_context context, krb5_error_code ret; krb5_principal sprinc; - ret = _krb5_principalname2krb5_principal(context, &sprinc, t->sname, t->realm); + ret = _krb5_principalname2krb5_principal(context, &sprinc, + t->sname, t->realm); if (ret) { kdc_log(context, config, 0, "_krb5_principalname2krb5_principal: %s", krb5_get_err_text(context, ret)); @@ -66,7 +67,8 @@ fetch_server (krb5_context context, krb5_get_err_text(context, ret)); return ret; } - ret = _kdc_db_fetch(context, config, sprinc, HDB_F_GET_SERVER, server); + ret = _kdc_db_fetch(context, config, sprinc, HDB_F_GET_SERVER, + NULL, server); krb5_free_principal(context, sprinc); if (ret) { kdc_log(context, config, 0, @@ -90,7 +92,8 @@ log_524 (krb5_context context, char *cpn; krb5_error_code ret; - ret = _krb5_principalname2krb5_principal(context, &client, et->cname, et->crealm); + ret = _krb5_principalname2krb5_principal(context, &client, + et->cname, et->crealm); if (ret) { kdc_log(context, config, 0, "_krb5_principalname2krb5_principal: %s", krb5_get_err_text (context, ret)); diff --git a/source4/heimdal/kdc/default_config.c b/source4/heimdal/kdc/default_config.c index 5152fe9ab1..c4d9f51fd0 100644 --- a/source4/heimdal/kdc/default_config.c +++ b/source4/heimdal/kdc/default_config.c @@ -42,8 +42,9 @@ void krb5_kdc_default_config(krb5_kdc_configuration *config) { + memset(config, 0, sizeof(*config)); config->require_preauth = TRUE; - config->kdc_warn_pwexpire = -1; + config->kdc_warn_pwexpire = 0; config->encode_as_rep_as_tgs_rep = FALSE; /* bug compatibility */ config->check_ticket_addresses = TRUE; config->allow_null_ticket_addresses = TRUE; diff --git a/source4/heimdal/kdc/digest.c b/source4/heimdal/kdc/digest.c new file mode 100644 index 0000000000..a5517fb896 --- /dev/null +++ b/source4/heimdal/kdc/digest.c @@ -0,0 +1,712 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kdc_locl.h" +#include <digest_asn1.h> +#include <hex.h> + +RCSID("$Id: digest.c,v 1.7 2006/10/22 20:11:44 lha Exp $"); + +krb5_error_code +_kdc_do_digest(krb5_context context, + krb5_kdc_configuration *config, + const DigestREQ *req, krb5_data *reply, + const char *from, struct sockaddr *addr) +{ + krb5_error_code ret = 0; + krb5_ticket *ticket = NULL; + krb5_auth_context ac = NULL; + krb5_keytab id = NULL; + krb5_crypto crypto = NULL; + DigestReqInner ireq; + DigestRepInner r; + DigestREP rep; + krb5_flags ap_req_options; + krb5_data buf; + size_t size; + krb5_storage *sp = NULL; + Checksum res; + hdb_entry_ex *server = NULL, *user = NULL; + char *password = NULL; + krb5_data serverNonce; + + if(!config->enable_digest) { + kdc_log(context, config, 0, "Rejected digest request from %s", from); + return KRB5KDC_ERR_POLICY; + } + + krb5_data_zero(&buf); + krb5_data_zero(reply); + krb5_data_zero(&serverNonce); + memset(&ireq, 0, sizeof(ireq)); + memset(&r, 0, sizeof(r)); + memset(&rep, 0, sizeof(rep)); + + kdc_log(context, config, 0, "Digest request from %s", from); + + ret = krb5_kt_resolve(context, "HDB:", &id); + if (ret) { + kdc_log(context, config, 0, "Can't open database for digest"); + goto out; + } + + ret = krb5_rd_req(context, + &ac, + &req->apReq, + NULL, + id, + &ap_req_options, + &ticket); + if (ret) + goto out; + + /* check the server principal in the ticket matches digest/R@R */ + { + krb5_principal principal = NULL; + const char *p, *r; + + ret = krb5_ticket_get_server(context, ticket, &principal); + if (ret) + goto out; + + ret = EINVAL; + krb5_set_error_string(context, "Wrong digest server principal used"); + p = krb5_principal_get_comp_string(context, principal, 0); + if (p == NULL) { + krb5_free_principal(context, principal); + goto out; + } + if (strcmp(p, KRB5_DIGEST_NAME) != 0) { + krb5_free_principal(context, principal); + goto out; + } + + p = krb5_principal_get_comp_string(context, principal, 1); + if (p == NULL) { + krb5_free_principal(context, principal); + goto out; + } + r = krb5_principal_get_realm(context, principal); + if (r == NULL) { + krb5_free_principal(context, principal); + goto out; + } + if (strcmp(p, r) != 0) { + krb5_free_principal(context, principal); + goto out; + } + + ret = _kdc_db_fetch(context, config, principal, + HDB_F_GET_SERVER, NULL, &server); + if (ret) + goto out; + + krb5_free_principal(context, principal); + } + + /* check the client is allowed to do digest auth */ + { + krb5_principal principal = NULL; + hdb_entry_ex *client; + + ret = krb5_ticket_get_client(context, ticket, &principal); + if (ret) + goto out; + + ret = _kdc_db_fetch(context, config, principal, + HDB_F_GET_CLIENT, NULL, &client); + krb5_free_principal(context, principal); + if (ret) + goto out; + + if (client->entry.flags.allow_digest == 0) { + krb5_set_error_string(context, + "Client is not permitted to use digest"); + ret = KRB5KDC_ERR_POLICY; + _kdc_free_ent (context, client); + goto out; + } + _kdc_free_ent (context, client); + } + + /* unpack request */ + { + krb5_keyblock *key; + + ret = krb5_auth_con_getremotesubkey(context, ac, &key); + if (ret) + goto out; + if (key == NULL) { + krb5_set_error_string(context, "digest: remote subkey not found"); + ret = EINVAL; + goto out; + } + + ret = krb5_crypto_init(context, key, 0, &crypto); + krb5_free_keyblock (context, key); + if (ret) + goto out; + } + + ret = krb5_decrypt_EncryptedData(context, crypto, KRB5_KU_DIGEST_ENCRYPT, + &req->innerReq, &buf); + krb5_crypto_destroy(context, crypto); + crypto = NULL; + if (ret) + goto out; + + ret = decode_DigestReqInner(buf.data, buf.length, &ireq, NULL); + krb5_data_free(&buf); + if (ret) { + krb5_set_error_string(context, "Failed to decode digest inner request"); + goto out; + } + + /* + * Process the inner request + */ + + switch (ireq.element) { + case choice_DigestReqInner_init: { + unsigned char server_nonce[16], identifier; + + RAND_pseudo_bytes(&identifier, sizeof(identifier)); + RAND_pseudo_bytes(server_nonce, sizeof(server_nonce)); + + server_nonce[0] = kdc_time & 0xff; + server_nonce[1] = (kdc_time >> 8) & 0xff; + server_nonce[2] = (kdc_time >> 16) & 0xff; + server_nonce[3] = (kdc_time >> 24) & 0xff; + + r.element = choice_DigestRepInner_initReply; + + hex_encode(server_nonce, sizeof(server_nonce), &r.u.initReply.nonce); + if (r.u.initReply.nonce == NULL) { + krb5_set_error_string(context, "Failed to decode server nonce"); + ret = ENOMEM; + goto out; + } + + sp = krb5_storage_emem(); + if (sp == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "out of memory"); + goto out; + } + ret = krb5_store_stringz(sp, ireq.u.init.type); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + + if (ireq.u.init.channel) { + char *s; + + asprintf(&s, "%s-%s:%s", r.u.initReply.nonce, + ireq.u.init.channel->cb_type, + ireq.u.init.channel->cb_binding); + if (s == NULL) { + krb5_set_error_string(context, "Failed to allocate " + "channel binding"); + ret = ENOMEM; + goto out; + } + free(r.u.initReply.nonce); + r.u.initReply.nonce = s; + } + + ret = krb5_store_stringz(sp, r.u.initReply.nonce); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + + if (strcasecmp(ireq.u.init.type, "CHAP") == 0) { + r.u.initReply.identifier = + malloc(sizeof(*r.u.initReply.identifier)); + if (r.u.initReply.identifier == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + + asprintf(r.u.initReply.identifier, "%02X", identifier & 0xff); + if (*r.u.initReply.identifier == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + + ret = krb5_store_stringz(sp, *r.u.initReply.identifier); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + } else + r.u.initReply.identifier = NULL; + + if (ireq.u.init.hostname) { + ret = krb5_store_stringz(sp, *ireq.u.init.hostname); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + } + + ret = krb5_storage_to_data(sp, &buf); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + + { + Key *key; + krb5_enctype enctype; + + ret = _kdc_get_preferred_key(context, + config, + server, + "digest-service", + &enctype, + &key); + if (ret) + goto out; + ret = krb5_crypto_init(context, &key->key, 0, &crypto); + if (ret) + goto out; + } + + ret = krb5_create_checksum(context, + crypto, + KRB5_KU_DIGEST_OPAQUE, + 0, + buf.data, + buf.length, + &res); + krb5_crypto_destroy(context, crypto); + crypto = NULL; + krb5_data_free(&buf); + if (ret) + goto out; + + ASN1_MALLOC_ENCODE(Checksum, buf.data, buf.length, &res, &size, ret); + free_Checksum(&res); + if (ret) { + krb5_set_error_string(context, "Failed to encode " + "checksum in digest request"); + goto out; + } + if (size != buf.length) + krb5_abortx(context, "ASN1 internal error"); + + hex_encode(buf.data, buf.length, &r.u.initReply.opaque); + free(buf.data); + if (r.u.initReply.opaque == NULL) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + break; + } + case choice_DigestReqInner_digestRequest: { + krb5_principal clientprincipal; + HDB *db; + + sp = krb5_storage_emem(); + if (sp == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "out of memory"); + goto out; + } + krb5_store_stringz(sp, ireq.u.digestRequest.type); + + krb5_store_stringz(sp, ireq.u.digestRequest.serverNonce); + if (ireq.u.digestRequest.identifier) { + ret = krb5_store_stringz(sp, *ireq.u.digestRequest.identifier); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + } + if (ireq.u.digestRequest.hostname) { + ret = krb5_store_stringz(sp, *ireq.u.digestRequest.hostname); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + } + + buf.length = strlen(ireq.u.digestRequest.opaque); + buf.data = malloc(buf.length); + if (buf.data == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + + ret = hex_decode(ireq.u.digestRequest.opaque, buf.data, buf.length); + if (ret <= 0) { + krb5_set_error_string(context, "Failed to decode opaque"); + ret = ENOMEM; + goto out; + } + buf.length = ret; + + ret = decode_Checksum(buf.data, buf.length, &res, NULL); + free(buf.data); + if (ret) { + krb5_set_error_string(context, "Failed to decode digest Checksum"); + goto out; + } + + ret = krb5_storage_to_data(sp, &buf); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + + serverNonce.length = strlen(ireq.u.digestRequest.serverNonce); + serverNonce.data = malloc(serverNonce.length); + if (serverNonce.data == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + + /* + * CHAP does the checksum of the raw nonce, but do it for all + * types, since we need to check the timestamp. + */ + { + ssize_t ssize; + + ssize = hex_decode(ireq.u.digestRequest.serverNonce, + serverNonce.data, serverNonce.length); + if (ssize <= 0) { + krb5_set_error_string(context, "Failed to decode serverNonce"); + ret = ENOMEM; + goto out; + } + serverNonce.length = ssize; + } + + { + Key *key; + krb5_enctype enctype; + + ret = _kdc_get_preferred_key(context, + config, + server, + "digest-service", + &enctype, + &key); + if (ret) + goto out; + ret = krb5_crypto_init(context, &key->key, 0, &crypto); + if (ret) + goto out; + } + + ret = krb5_verify_checksum(context, crypto, + KRB5_KU_DIGEST_OPAQUE, + buf.data, buf.length, &res); + krb5_crypto_destroy(context, crypto); + crypto = NULL; + if (ret) + goto out; + + /* verify time */ + { + unsigned char *p = serverNonce.data; + uint32_t t; + + if (serverNonce.length < 4) { + krb5_set_error_string(context, "server nonce too short"); + ret = EINVAL; + goto out; + } + t = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); + + if (abs((kdc_time & 0xffffffff) - t) > context->max_skew) { + krb5_set_error_string(context, "time screw in server nonce "); + ret = EINVAL; + goto out; + } + } + + /* get username */ + ret = krb5_parse_name(context, + ireq.u.digestRequest.username, + &clientprincipal); + if (ret) + goto out; + + ret = _kdc_db_fetch(context, config, clientprincipal, + HDB_F_GET_CLIENT, &db, &user); + + krb5_free_principal(context, clientprincipal); + if (ret) + goto out; + + ret = hdb_entry_get_password(context, db, &user->entry, &password); + if (ret || password == NULL) { + if (ret == 0) { + ret = EINVAL; + krb5_set_error_string(context, "password missing"); + } + goto out; + } + + if (strcasecmp(ireq.u.digestRequest.type, "CHAP") == 0) { + MD5_CTX ctx; + unsigned char md[MD5_DIGEST_LENGTH]; + char id; + + if (ireq.u.digestRequest.identifier == NULL) { + krb5_set_error_string(context, "Identifier missing " + "from CHAP request"); + ret = EINVAL; + goto out; + } + + if (hex_decode(*ireq.u.digestRequest.identifier, &id, 1) != 1) { + krb5_set_error_string(context, "failed to decode identifier"); + ret = EINVAL; + goto out; + } + + MD5_Init(&ctx); + MD5_Update(&ctx, &id, 1); + MD5_Update(&ctx, password, strlen(password)); + MD5_Update(&ctx, serverNonce.data, serverNonce.length); + MD5_Final(md, &ctx); + + r.element = choice_DigestRepInner_response; + hex_encode(md, sizeof(md), &r.u.response.responseData); + if (r.u.response.responseData == NULL) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + } else if (strcasecmp(ireq.u.digestRequest.type, "SASL-DIGEST-MD5") == 0) { + MD5_CTX ctx; + unsigned char md[MD5_DIGEST_LENGTH]; + char *A1, *A2; + + if (ireq.u.digestRequest.nonceCount == NULL) + goto out; + if (ireq.u.digestRequest.clientNonce == NULL) + goto out; + if (ireq.u.digestRequest.qop == NULL) + goto out; + if (ireq.u.digestRequest.realm == NULL) + goto out; + + MD5_Init(&ctx); + MD5_Update(&ctx, ireq.u.digestRequest.username, + strlen(ireq.u.digestRequest.username)); + MD5_Update(&ctx, ":", 1); + MD5_Update(&ctx, *ireq.u.digestRequest.realm, + strlen(*ireq.u.digestRequest.realm)); + MD5_Update(&ctx, ":", 1); + MD5_Update(&ctx, password, strlen(password)); + MD5_Final(md, &ctx); + + MD5_Init(&ctx); + MD5_Update(&ctx, md, sizeof(md)); + MD5_Update(&ctx, ":", 1); + MD5_Update(&ctx, ireq.u.digestRequest.serverNonce, + strlen(ireq.u.digestRequest.serverNonce)); + MD5_Update(&ctx, ":", 1); + MD5_Update(&ctx, *ireq.u.digestRequest.nonceCount, + strlen(*ireq.u.digestRequest.nonceCount)); + if (ireq.u.digestRequest.authid) { + MD5_Update(&ctx, ":", 1); + MD5_Update(&ctx, *ireq.u.digestRequest.authid, + strlen(*ireq.u.digestRequest.authid)); + } + MD5_Final(md, &ctx); + hex_encode(md, sizeof(md), &A1); + if (A1 == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + + MD5_Init(&ctx); + MD5_Update(&ctx, "AUTHENTICATE:", sizeof("AUTHENTICATE:") - 1); + MD5_Update(&ctx, *ireq.u.digestRequest.uri, + strlen(*ireq.u.digestRequest.uri)); + + /* conf|int */ + if (strcmp(ireq.u.digestRequest.digest, "clear") != 0) { + static char conf_zeros[] = ":00000000000000000000000000000000"; + MD5_Update(&ctx, conf_zeros, sizeof(conf_zeros) - 1); + } + + MD5_Final(md, &ctx); + hex_encode(md, sizeof(md), &A2); + if (A2 == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + free(A1); + goto out; + } + + MD5_Init(&ctx); + MD5_Update(&ctx, A1, strlen(A2)); + MD5_Update(&ctx, ":", 1); + MD5_Update(&ctx, ireq.u.digestRequest.serverNonce, + strlen(ireq.u.digestRequest.serverNonce)); + MD5_Update(&ctx, ":", 1); + MD5_Update(&ctx, *ireq.u.digestRequest.nonceCount, + strlen(*ireq.u.digestRequest.nonceCount)); + MD5_Update(&ctx, ":", 1); + MD5_Update(&ctx, *ireq.u.digestRequest.clientNonce, + strlen(*ireq.u.digestRequest.clientNonce)); + MD5_Update(&ctx, ":", 1); + MD5_Update(&ctx, *ireq.u.digestRequest.qop, + strlen(*ireq.u.digestRequest.qop)); + MD5_Update(&ctx, ":", 1); + MD5_Update(&ctx, A2, strlen(A2)); + + MD5_Final(md, &ctx); + + r.element = choice_DigestRepInner_response; + hex_encode(md, sizeof(md), &r.u.response.responseData); + + free(A1); + free(A2); + + if (r.u.response.responseData == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + + } else { + r.element = choice_DigestRepInner_error; + asprintf(&r.u.error.reason, "unsupported digest type %s", + ireq.u.digestRequest.type); + if (r.u.error.reason == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + r.u.error.code = EINVAL; + } + + break; + } + default: + r.element = choice_DigestRepInner_error; + r.u.error.reason = strdup("unknown operation"); + if (r.u.error.reason == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + r.u.error.code = EINVAL; + break; + } + + ASN1_MALLOC_ENCODE(DigestRepInner, buf.data, buf.length, &r, &size, ret); + if (ret) { + krb5_set_error_string(context, "Failed to encode inner digest reply"); + goto out; + } + if (size != buf.length) + krb5_abortx(context, "ASN1 internal error"); + + krb5_auth_con_addflags(context, ac, KRB5_AUTH_CONTEXT_USE_SUBKEY, NULL); + + ret = krb5_mk_rep (context, ac, &rep.apRep); + if (ret) + goto out; + + { + krb5_keyblock *key; + + ret = krb5_auth_con_getlocalsubkey(context, ac, &key); + if (ret) + goto out; + + ret = krb5_crypto_init(context, key, 0, &crypto); + krb5_free_keyblock (context, key); + if (ret) + goto out; + } + + ret = krb5_encrypt_EncryptedData(context, crypto, KRB5_KU_DIGEST_ENCRYPT, + buf.data, buf.length, 0, + &rep.innerRep); + + ASN1_MALLOC_ENCODE(DigestREP, reply->data, reply->length, &rep, &size, ret); + if (ret) { + krb5_set_error_string(context, "Failed to encode digest reply"); + goto out; + } + if (size != reply->length) + krb5_abortx(context, "ASN1 internal error"); + + +out: + if (ac) + krb5_auth_con_free(context, ac); + if (ret) + krb5_warn(context, ret, "Digest request from %s failed", from); + if (ticket) + krb5_free_ticket(context, ticket); + if (id) + krb5_kt_close(context, id); + if (crypto) + krb5_crypto_destroy(context, crypto); + if (sp) + krb5_storage_free(sp); + if (user) + _kdc_free_ent (context, user); + if (server) + _kdc_free_ent (context, server); + if (password) { + memset(password, 0, strlen(password)); + free (password); + } + krb5_data_free(&buf); + krb5_data_free(&serverNonce); + free_DigestREP(&rep); + free_DigestRepInner(&r); + free_DigestReqInner(&ireq); + + return ret; +} diff --git a/source4/heimdal/kdc/headers.h b/source4/heimdal/kdc/headers.h index 86f162aa94..87d713b076 100644 --- a/source4/heimdal/kdc/headers.h +++ b/source4/heimdal/kdc/headers.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -32,7 +32,7 @@ */ /* - * $Id: headers.h,v 1.16 2005/04/24 13:49:00 lha Exp $ + * $Id: headers.h,v 1.18 2006/10/17 02:22:17 lha Exp $ */ #ifndef __HEADERS_H__ @@ -88,9 +88,10 @@ #include <parse_units.h> #include <krb5.h> #include <krb5_locl.h> +#include <digest_asn1.h> #include <hdb.h> #include <hdb_err.h> -#include <der.h> /* copy_octet_string */ +#include <der.h> #undef ALLOC #define ALLOC(X) ((X) = malloc(sizeof(*(X)))) diff --git a/source4/heimdal/kdc/kaserver.c b/source4/heimdal/kdc/kaserver.c index c08a51b9cc..ac282717ed 100644 --- a/source4/heimdal/kdc/kaserver.c +++ b/source4/heimdal/kdc/kaserver.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: kaserver.c,v 1.35 2006/05/05 10:49:50 lha Exp $"); +RCSID("$Id: kaserver.c,v 1.36 2006/08/23 11:43:44 lha Exp $"); #include <krb5-v4compat.h> #include <rx.h> @@ -465,7 +465,8 @@ do_authenticate (krb5_context context, client_name, from, server_name); ret = _kdc_db_fetch4 (context, config, name, instance, - config->v4_realm, HDB_F_GET_CLIENT, &client_entry); + config->v4_realm, HDB_F_GET_CLIENT, + &client_entry); if (ret) { kdc_log(context, config, 0, "Client not found in database: %s: %s", client_name, krb5_get_err_text(context, ret)); diff --git a/source4/heimdal/kdc/kdc-private.h b/source4/heimdal/kdc/kdc-private.h index 251e06b14a..8c2f56002d 100644 --- a/source4/heimdal/kdc/kdc-private.h +++ b/source4/heimdal/kdc/kdc-private.h @@ -5,6 +5,16 @@ #include <stdarg.h> krb5_error_code +_kdc_add_KRB5SignedPath ( + krb5_context /*context*/, + krb5_kdc_configuration */*config*/, + hdb_entry_ex */*krbtgt*/, + krb5_enctype /*enctype*/, + krb5_const_principal /*server*/, + KRB5SignedPathPrincipals */*principals*/, + EncTicketPart */*tkt*/); + +krb5_error_code _kdc_as_rep ( krb5_context /*context*/, krb5_kdc_configuration */*config*/, @@ -12,7 +22,15 @@ _kdc_as_rep ( const krb5_data */*req_buffer*/, krb5_data */*reply*/, const char */*from*/, - struct sockaddr */*from_addr*/); + struct sockaddr */*from_addr*/, + int /*datagram_reply*/); + +krb5_boolean +_kdc_check_addresses ( + krb5_context /*context*/, + krb5_kdc_configuration */*config*/, + HostAddresses */*addresses*/, + const struct sockaddr */*from*/); krb5_error_code _kdc_check_flags ( @@ -30,6 +48,7 @@ _kdc_db_fetch ( krb5_kdc_configuration */*config*/, krb5_const_principal /*principal*/, unsigned /*flags*/, + HDB **/*db*/, hdb_entry_ex **/*h*/); krb5_error_code @@ -52,6 +71,15 @@ _kdc_do_524 ( struct sockaddr */*addr*/); krb5_error_code +_kdc_do_digest ( + krb5_context /*context*/, + krb5_kdc_configuration */*config*/, + const DigestREQ */*req*/, + krb5_data */*reply*/, + const char */*from*/, + struct sockaddr */*addr*/); + +krb5_error_code _kdc_do_kaserver ( krb5_context /*context*/, krb5_kdc_configuration */*config*/, @@ -72,6 +100,21 @@ _kdc_do_version4 ( struct sockaddr_in */*addr*/); krb5_error_code +_kdc_encode_reply ( + krb5_context /*context*/, + krb5_kdc_configuration */*config*/, + KDC_REP */*rep*/, + const EncTicketPart */*et*/, + EncKDCRepPart */*ek*/, + krb5_enctype /*etype*/, + int /*skvno*/, + const EncryptionKey */*skey*/, + int /*ckvno*/, + const EncryptionKey */*ckey*/, + const char **/*e_text*/, + krb5_data */*reply*/); + +krb5_error_code _kdc_encode_v4_ticket ( krb5_context /*context*/, krb5_kdc_configuration */*config*/, @@ -81,6 +124,24 @@ _kdc_encode_v4_ticket ( const PrincipalName */*service*/, size_t */*size*/); +krb5_error_code +_kdc_find_etype ( + krb5_context /*context*/, + const hdb_entry_ex */*princ*/, + krb5_enctype */*etypes*/, + unsigned /*len*/, + Key **/*ret_key*/, + krb5_enctype */*ret_etype*/); + +PA_DATA* +_kdc_find_padata ( + KDC_REQ */*req*/, + int */*start*/, + int /*type*/); + +void +_kdc_fix_time (time_t **/*t*/); + void _kdc_free_ent ( krb5_context /*context*/, @@ -94,6 +155,28 @@ _kdc_get_des_key ( krb5_boolean /*prefer_afs_key*/, Key **/*ret_key*/); +krb5_error_code +_kdc_get_preferred_key ( + krb5_context /*context*/, + krb5_kdc_configuration */*config*/, + hdb_entry_ex */*h*/, + const char */*name*/, + krb5_enctype */*enctype*/, + Key **/*key*/); + +void +_kdc_log_timestamp ( + krb5_context /*context*/, + krb5_kdc_configuration */*config*/, + const char */*type*/, + KerberosTime /*authtime*/, + KerberosTime */*starttime*/, + KerberosTime /*endtime*/, + KerberosTime */*renew_till*/); + +krb5_error_code +_kdc_make_anonymous_principalname (PrincipalName */*pn*/); + int _kdc_maybe_version4 ( unsigned char */*buf*/, @@ -120,7 +203,7 @@ _kdc_pk_initialize ( const char */*user_id*/, const char */*anchors*/, char **/*pool*/, - char **/*revoke*/); + char **/*revoke_list*/); krb5_error_code _kdc_pk_mk_pa_reply ( diff --git a/source4/heimdal/kdc/kdc-protos.h b/source4/heimdal/kdc/kdc-protos.h index 5967f933f3..69bc871b01 100644 --- a/source4/heimdal/kdc/kdc-protos.h +++ b/source4/heimdal/kdc/kdc-protos.h @@ -41,25 +41,27 @@ void krb5_kdc_default_config (krb5_kdc_configuration */*config*/); int -krb5_kdc_process_generic_request ( +krb5_kdc_process_krb5_request ( krb5_context /*context*/, krb5_kdc_configuration */*config*/, unsigned char */*buf*/, size_t /*len*/, krb5_data */*reply*/, - krb5_boolean */*prependlength*/, const char */*from*/, - struct sockaddr */*addr*/); + struct sockaddr */*addr*/, + int /*datagram_reply*/); int -krb5_kdc_process_krb5_request ( +krb5_kdc_process_request ( krb5_context /*context*/, krb5_kdc_configuration */*config*/, unsigned char */*buf*/, size_t /*len*/, krb5_data */*reply*/, + krb5_boolean */*prependlength*/, const char */*from*/, - struct sockaddr */*addr*/); + struct sockaddr */*addr*/, + int /*datagram_reply*/); #ifdef __cplusplus } diff --git a/source4/heimdal/kdc/kdc.h b/source4/heimdal/kdc/kdc.h index 2948570e3a..043b6de47d 100644 --- a/source4/heimdal/kdc/kdc.h +++ b/source4/heimdal/kdc/kdc.h @@ -35,7 +35,7 @@ */ /* - * $Id: kdc.h,v 1.6 2006/05/03 12:03:29 lha Exp $ + * $Id: kdc.h,v 1.9 2006/10/09 15:34:07 lha Exp $ */ #ifndef __KDC_H__ @@ -65,10 +65,12 @@ typedef struct krb5_kdc_configuration { char *v4_realm; krb5_boolean enable_v4; + krb5_boolean enable_v4_cross_realm; + krb5_boolean enable_v4_per_principal; + krb5_boolean enable_kaserver; - + krb5_boolean enable_524; - krb5_boolean enable_v4_cross_realm; krb5_boolean enable_pkinit; krb5_boolean enable_pkinit_princ_in_cert; @@ -78,6 +80,9 @@ typedef struct krb5_kdc_configuration { int pkinit_dh_min_bits; + int enable_digest; + size_t max_datagram_reply_length; + } krb5_kdc_configuration; #include <kdc-protos.h> diff --git a/source4/heimdal/kdc/kerberos4.c b/source4/heimdal/kdc/kerberos4.c index d7a3a9cb69..97e98d86ad 100644 --- a/source4/heimdal/kdc/kerberos4.c +++ b/source4/heimdal/kdc/kerberos4.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -35,7 +35,7 @@ #include <krb5-v4compat.h> -RCSID("$Id: kerberos4.c,v 1.60 2006/05/05 10:50:44 lha Exp $"); +RCSID("$Id: kerberos4.c,v 1.63 2006/10/08 13:43:27 lha Exp $"); #ifndef swap32 static uint32_t @@ -80,7 +80,7 @@ valid_princ(krb5_context context, ret = krb5_unparse_name(context, princ, &s); if (ret) return FALSE; - ret = _kdc_db_fetch(context, ctx->config, princ, ctx->flags, &ent); + ret = _kdc_db_fetch(context, ctx->config, princ, ctx->flags, NULL, &ent); if (ret) { kdc_log(context, ctx->config, 7, "Lookup %s failed: %s", s, krb5_get_err_text (context, ret)); @@ -111,7 +111,7 @@ _kdc_db_fetch4(krb5_context context, valid_princ, &ctx, 0, &p); if(ret) return ret; - ret = _kdc_db_fetch(context, config, p, flags, ent); + ret = _kdc_db_fetch(context, config, p, flags, NULL, ent); krb5_free_principal(context, p); return ret; } @@ -221,6 +221,17 @@ _kdc_do_version4(krb5_context context, goto out1; } + if (config->enable_v4_per_principal && + client->entry.flags.allow_kerberos4 == 0) + { + kdc_log(context, config, 0, + "Per principal Kerberos 4 flag not turned on for %s", + client_name); + make_err_reply(context, reply, KERB_ERR_NULL_KEY, + "allow kerberos4 flag required"); + goto out1; + } + /* * There's no way to do pre-authentication in v4 and thus no * good error code to return if preauthentication is required. @@ -372,7 +383,7 @@ _kdc_do_version4(krb5_context context, } ret = _kdc_db_fetch(context, config, tgt_princ, - HDB_F_GET_KRBTGT, &tgt); + HDB_F_GET_KRBTGT, NULL, &tgt); if(ret){ char *s; s = kdc_log_msg(context, config, 0, "Ticket-granting ticket not " @@ -668,7 +679,7 @@ _kdc_encode_v4_ticket(krb5_context context, if(ret) return ret; - _krb5_principalname2krb5_principal(context, + _krb5_principalname2krb5_principal(context, &princ, et->cname, et->crealm); diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c index a73c2c10b3..19287b31cc 100644 --- a/source4/heimdal/kdc/kerberos5.c +++ b/source4/heimdal/kdc/kerberos5.c @@ -33,12 +33,12 @@ #include "kdc_locl.h" -RCSID("$Id: kerberos5.c,v 1.211 2006/04/27 12:01:09 lha Exp $"); +RCSID("$Id: kerberos5.c,v 1.223 2006/10/17 02:16:29 lha Exp $"); #define MAX_TIME ((time_t)((1U << 31) - 1)) -static void -fix_time(time_t **t) +void +_kdc_fix_time(time_t **t) { if(*t == NULL){ ALLOC(*t); @@ -65,13 +65,13 @@ set_salt_padata (METHOD_DATA *md, Salt *salt) if (salt) { realloc_method_data(md); md->val[md->len - 1].padata_type = salt->type; - copy_octet_string(&salt->salt, - &md->val[md->len - 1].padata_value); + der_copy_octet_string(&salt->salt, + &md->val[md->len - 1].padata_value); } } -static PA_DATA* -find_padata(KDC_REQ *req, int *start, int type) +PA_DATA* +_kdc_find_padata(KDC_REQ *req, int *start, int type) { while(*start < req->padata->len){ (*start)++; @@ -87,10 +87,10 @@ find_padata(KDC_REQ *req, int *start, int type) * one, but preferring one that has default salt */ -static krb5_error_code -find_etype(krb5_context context, const hdb_entry_ex *princ, - krb5_enctype *etypes, unsigned len, - Key **ret_key, krb5_enctype *ret_etype) +krb5_error_code +_kdc_find_etype(krb5_context context, const hdb_entry_ex *princ, + krb5_enctype *etypes, unsigned len, + Key **ret_key, krb5_enctype *ret_etype) { int i; krb5_error_code ret = KRB5KDC_ERR_ETYPE_NOSUPP; @@ -116,46 +116,8 @@ find_etype(krb5_context context, const hdb_entry_ex *princ, return ret; } -static krb5_error_code -find_keys(krb5_context context, - krb5_kdc_configuration *config, - const hdb_entry_ex *client, - const char *client_name, - const hdb_entry_ex *server, - const char *server_name, - Key **ckey, - krb5_enctype *cetype, - Key **skey, - krb5_enctype *setype, - krb5_enctype *etypes, - unsigned num_etypes) -{ - krb5_error_code ret; - - if(client){ - /* find client key */ - ret = find_etype(context, client, etypes, num_etypes, ckey, cetype); - if (ret) { - kdc_log(context, config, 0, - "Client (%s) has no support for etypes", client_name); - return ret; - } - } - - if(server){ - /* find server key */ - ret = find_etype(context, server, etypes, num_etypes, skey, setype); - if (ret) { - kdc_log(context, config, 0, - "Server (%s) has no support for etypes", server_name); - return ret; - } - } - return 0; -} - -static krb5_error_code -make_anonymous_principalname (PrincipalName *pn) +krb5_error_code +_kdc_make_anonymous_principalname (PrincipalName *pn) { pn->name_type = KRB5_NT_PRINCIPAL; pn->name_string.len = 1; @@ -171,12 +133,12 @@ make_anonymous_principalname (PrincipalName *pn) return 0; } -static void -log_timestamp(krb5_context context, - krb5_kdc_configuration *config, - const char *type, - KerberosTime authtime, KerberosTime *starttime, - KerberosTime endtime, KerberosTime *renew_till) +void +_kdc_log_timestamp(krb5_context context, + krb5_kdc_configuration *config, + const char *type, + KerberosTime authtime, KerberosTime *starttime, + KerberosTime endtime, KerberosTime *renew_till) { char authtime_str[100], starttime_str[100], endtime_str[100], renewtime_str[100]; @@ -248,15 +210,15 @@ log_patypes(krb5_context context, */ -static krb5_error_code -encode_reply(krb5_context context, - krb5_kdc_configuration *config, - KDC_REP *rep, EncTicketPart *et, EncKDCRepPart *ek, - krb5_enctype etype, - int skvno, EncryptionKey *skey, - int ckvno, EncryptionKey *ckey, - const char **e_text, - krb5_data *reply) +krb5_error_code +_kdc_encode_reply(krb5_context context, + krb5_kdc_configuration *config, + KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek, + krb5_enctype etype, + int skvno, const EncryptionKey *skey, + int ckvno, const EncryptionKey *ckey, + const char **e_text, + krb5_data *reply) { unsigned char *buf; size_t buf_size; @@ -795,10 +757,10 @@ _kdc_check_flags(krb5_context context, * these checks */ -static krb5_boolean -check_addresses(krb5_context context, - krb5_kdc_configuration *config, - HostAddresses *addresses, const struct sockaddr *from) +krb5_boolean +_kdc_check_addresses(krb5_context context, + krb5_kdc_configuration *config, + HostAddresses *addresses, const struct sockaddr *from) { krb5_error_code ret; krb5_address addr; @@ -843,13 +805,14 @@ _kdc_as_rep(krb5_context context, const krb5_data *req_buffer, krb5_data *reply, const char *from, - struct sockaddr *from_addr) + struct sockaddr *from_addr, + int datagram_reply) { KDC_REQ_BODY *b = &req->req_body; AS_REP rep; KDCOptions f = b->kdc_options; hdb_entry_ex *client = NULL, *server = NULL; - krb5_enctype cetype, setype; + krb5_enctype cetype, setype, sessionetype; EncTicketPart et; EncKDCRepPart ek; krb5_principal client_princ = NULL, server_princ = NULL; @@ -869,12 +832,15 @@ _kdc_as_rep(krb5_context context, ret = KRB5KRB_ERR_GENERIC; e_text = "No server in request"; } else{ - _krb5_principalname2krb5_principal (context, &server_princ, - *(b->sname), b->realm); + _krb5_principalname2krb5_principal (context, + &server_princ, + *(b->sname), + b->realm); ret = krb5_unparse_name(context, server_princ, &server_name); } if (ret) { - kdc_log(context, config, 0, "AS-REQ malformed server name from %s", from); + kdc_log(context, config, 0, + "AS-REQ malformed server name from %s", from); goto out; } @@ -882,12 +848,15 @@ _kdc_as_rep(krb5_context context, ret = KRB5KRB_ERR_GENERIC; e_text = "No client in request"; } else { - _krb5_principalname2krb5_principal (context, &client_princ, - *(b->cname), b->realm); + _krb5_principalname2krb5_principal (context, + &client_princ, + *(b->cname), + b->realm); ret = krb5_unparse_name(context, client_princ, &client_name); } if (ret) { - kdc_log(context, config, 0, "AS-REQ malformed client name from %s", from); + kdc_log(context, config, 0, + "AS-REQ malformed client name from %s", from); goto out; } @@ -895,7 +864,7 @@ _kdc_as_rep(krb5_context context, client_name, from, server_name); ret = _kdc_db_fetch(context, config, client_princ, - HDB_F_GET_CLIENT, &client); + HDB_F_GET_CLIENT, NULL, &client); if(ret){ kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, krb5_get_err_text(context, ret)); @@ -904,7 +873,8 @@ _kdc_as_rep(krb5_context context, } ret = _kdc_db_fetch(context, config, server_princ, - HDB_F_GET_SERVER|HDB_F_GET_KRBTGT, &server); + HDB_F_GET_SERVER|HDB_F_GET_KRBTGT, + NULL, &server); if(ret){ kdc_log(context, config, 0, "UNKNOWN -- %s: %s", server_name, krb5_get_err_text(context, ret)); @@ -943,11 +913,11 @@ _kdc_as_rep(krb5_context context, e_text = "No PKINIT PA found"; i = 0; - if ((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ))) + if ((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ))) ; if (pa == NULL) { i = 0; - if((pa = find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN))) + if((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN))) ; } if (pa) { @@ -995,7 +965,7 @@ _kdc_as_rep(krb5_context context, i = 0; e_text = "No ENC-TS found"; - while((pa = find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){ + while((pa = _kdc_find_padata(req, &i, KRB5_PADATA_ENC_TIMESTAMP))){ krb5_data ts_data; PA_ENC_TS_ENC p; size_t len; @@ -1056,7 +1026,7 @@ _kdc_as_rep(krb5_context context, if(ret){ krb5_error_code ret2; ret2 = krb5_enctype_to_string(context, - pa_key->key.keytype, &str); + pa_key->key.keytype, &str); if (ret2) str = NULL; kdc_log(context, config, 5, @@ -1092,9 +1062,18 @@ _kdc_as_rep(krb5_context context, } free_PA_ENC_TS_ENC(&p); if (abs(kdc_time - p.patimestamp) > context->max_skew) { + char client_time[100]; + + krb5_format_time(context, p.patimestamp, + client_time, sizeof(client_time), TRUE); + ret = KRB5KRB_AP_ERR_SKEW; kdc_log(context, config, 0, - "Too large time skew -- %s", client_name); + "Too large time skew, client time %s is out by %u > %u seconds -- %s", + client_time, + (unsigned)abs(kdc_time - p.patimestamp), + context->max_skew, + client_name); /* * the following is needed to make windows clients * to retry using the timestamp in the error message @@ -1162,7 +1141,7 @@ _kdc_as_rep(krb5_context context, * both info replies (we send 'info' first in the list). * - If the client is 'modern', because it knows about 'new' * enctype types, then only send the 'info2' reply. - */ + */ /* XXX check ret */ if (only_older_enctype_p(req)) @@ -1197,14 +1176,54 @@ _kdc_as_rep(krb5_context context, goto out2; } - ret = find_keys(context, config, - client, client_name, - server, server_name, - &ckey, &cetype, &skey, &setype, - b->etype.val, b->etype.len); - if(ret) + /* + * Find the client key (for preauth ENC-TS verification and reply + * encryption). Then the best encryption type for the KDC and + * last the best session key that shared between the client and + * KDC runtime enctypes. + */ + + ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len, + &ckey, &cetype); + if (ret) { + kdc_log(context, config, 0, + "Client (%s) has no support for etypes", client_name); goto out; + } + ret = _kdc_get_preferred_key(context, config, + server, server_name, + &setype, &skey); + if(ret) + goto out; + + { + const krb5_enctype *p; + int i, j; + + p = krb5_kerberos_enctypes(context); + + sessionetype = ETYPE_NULL; + + for (i = 0; p[i] != ETYPE_NULL && sessionetype == ETYPE_NULL; i++) { + if (krb5_enctype_valid(context, p[i]) != 0) + continue; + for (j = 0; j < b->etype.len; j++) { + if (p[i] == b->etype.val[j]) { + sessionetype = p[i]; + break; + } + } + } + if (sessionetype == ETYPE_NULL) { + kdc_log(context, config, 0, + "Client (%s) from %s has no common enctypes with KDC" + "to use for the session key", + client_name, from); + goto out; + } + } + { struct rk_strpool *p = NULL; char *str; @@ -1268,9 +1287,9 @@ _kdc_as_rep(krb5_context context, rep.msg_type = krb_as_rep; copy_Realm(&client->entry.principal->realm, &rep.crealm); if (f.request_anonymous) - make_anonymous_principalname (&rep.cname); + _kdc_make_anonymous_principalname (&rep.cname); else - _krb5_principal2principalname(&rep.cname, + _krb5_principal2principalname(&rep.cname, client->entry.principal); rep.ticket.tkt_vno = 5; copy_Realm(&server->entry.principal->realm, &rep.ticket.realm); @@ -1304,14 +1323,14 @@ _kdc_as_rep(krb5_context context, } /* check for valid set of addresses */ - if(!check_addresses(context, config, b->addresses, from_addr)) { + if(!_kdc_check_addresses(context, config, b->addresses, from_addr)) { ret = KRB5KRB_AP_ERR_BADADDR; kdc_log(context, config, 0, "Bad address list requested -- %s", client_name); goto out; } - krb5_generate_random_keyblock(context, setype, &et.key); + krb5_generate_random_keyblock(context, sessionetype, &et.key); copy_PrincipalName(&rep.cname, &et.cname); copy_Realm(&rep.crealm, &et.crealm); @@ -1327,7 +1346,7 @@ _kdc_as_rep(krb5_context context, et.flags.invalid = 1; et.flags.postdated = 1; /* XXX ??? */ } - fix_time(&b->till); + _kdc_fix_time(&b->till); t = *b->till; /* be careful not overflowing */ @@ -1392,7 +1411,7 @@ _kdc_as_rep(krb5_context context, ek.last_req.len = 0; if (client->entry.pw_end && (config->kdc_warn_pwexpire == 0 - || kdc_time + config->kdc_warn_pwexpire <= *client->entry.pw_end)) { + || kdc_time + config->kdc_warn_pwexpire >= *client->entry.pw_end)) { ek.last_req.val[ek.last_req.len].lr_type = LR_PW_EXPTIME; ek.last_req.val[ek.last_req.len].lr_value = *client->entry.pw_end; ++ek.last_req.len; @@ -1472,15 +1491,37 @@ _kdc_as_rep(krb5_context context, goto out; } - log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime, - et.endtime, et.renew_till); + _kdc_log_timestamp(context, config, "AS-REQ", et.authtime, et.starttime, + et.endtime, et.renew_till); + + /* do this as the last thing since this signs the EncTicketPart */ + ret = _kdc_add_KRB5SignedPath(context, + config, + server, + setype, + NULL, + NULL, + &et); + if (ret) + goto out; - ret = encode_reply(context, config, - &rep, &et, &ek, setype, server->entry.kvno, &skey->key, - client->entry.kvno, reply_key, &e_text, reply); + ret = _kdc_encode_reply(context, config, + &rep, &et, &ek, setype, server->entry.kvno, + &skey->key, client->entry.kvno, + reply_key, &e_text, reply); free_EncTicketPart(&et); free_EncKDCRepPart(&ek); - out: + if (ret) + goto out; + + /* */ + if (datagram_reply && reply->length > config->max_datagram_reply_length) { + krb5_data_free(reply); + ret = KRB5KRB_ERR_RESPONSE_TOO_BIG; + e_text = "Reply packet too large"; + } + +out: free_AS_REP(&rep); if(ret){ krb5_mk_error(context, @@ -1494,7 +1535,7 @@ _kdc_as_rep(krb5_context context, reply); ret = 0; } - out2: +out2: #ifdef PKINIT if (pkp) _kdc_pk_free_client_param(context, pkp); @@ -1511,1089 +1552,3 @@ _kdc_as_rep(krb5_context context, _kdc_free_ent(context, server); return ret; } - - -static krb5_error_code -check_tgs_flags(krb5_context context, - krb5_kdc_configuration *config, - KDC_REQ_BODY *b, EncTicketPart *tgt, EncTicketPart *et) -{ - KDCOptions f = b->kdc_options; - - if(f.validate){ - if(!tgt->flags.invalid || tgt->starttime == NULL){ - kdc_log(context, config, 0, - "Bad request to validate ticket"); - return KRB5KDC_ERR_BADOPTION; - } - if(*tgt->starttime > kdc_time){ - kdc_log(context, config, 0, - "Early request to validate ticket"); - return KRB5KRB_AP_ERR_TKT_NYV; - } - /* XXX tkt = tgt */ - et->flags.invalid = 0; - }else if(tgt->flags.invalid){ - kdc_log(context, config, 0, - "Ticket-granting ticket has INVALID flag set"); - return KRB5KRB_AP_ERR_TKT_INVALID; - } - - if(f.forwardable){ - if(!tgt->flags.forwardable){ - kdc_log(context, config, 0, - "Bad request for forwardable ticket"); - return KRB5KDC_ERR_BADOPTION; - } - et->flags.forwardable = 1; - } - if(f.forwarded){ - if(!tgt->flags.forwardable){ - kdc_log(context, config, 0, - "Request to forward non-forwardable ticket"); - return KRB5KDC_ERR_BADOPTION; - } - et->flags.forwarded = 1; - et->caddr = b->addresses; - } - if(tgt->flags.forwarded) - et->flags.forwarded = 1; - - if(f.proxiable){ - if(!tgt->flags.proxiable){ - kdc_log(context, config, 0, - "Bad request for proxiable ticket"); - return KRB5KDC_ERR_BADOPTION; - } - et->flags.proxiable = 1; - } - if(f.proxy){ - if(!tgt->flags.proxiable){ - kdc_log(context, config, 0, - "Request to proxy non-proxiable ticket"); - return KRB5KDC_ERR_BADOPTION; - } - et->flags.proxy = 1; - et->caddr = b->addresses; - } - if(tgt->flags.proxy) - et->flags.proxy = 1; - - if(f.allow_postdate){ - if(!tgt->flags.may_postdate){ - kdc_log(context, config, 0, - "Bad request for post-datable ticket"); - return KRB5KDC_ERR_BADOPTION; - } - et->flags.may_postdate = 1; - } - if(f.postdated){ - if(!tgt->flags.may_postdate){ - kdc_log(context, config, 0, - "Bad request for postdated ticket"); - return KRB5KDC_ERR_BADOPTION; - } - if(b->from) - *et->starttime = *b->from; - et->flags.postdated = 1; - et->flags.invalid = 1; - }else if(b->from && *b->from > kdc_time + context->max_skew){ - kdc_log(context, config, 0, "Ticket cannot be postdated"); - return KRB5KDC_ERR_CANNOT_POSTDATE; - } - - if(f.renewable){ - if(!tgt->flags.renewable){ - kdc_log(context, config, 0, - "Bad request for renewable ticket"); - return KRB5KDC_ERR_BADOPTION; - } - et->flags.renewable = 1; - ALLOC(et->renew_till); - fix_time(&b->rtime); - *et->renew_till = *b->rtime; - } - if(f.renew){ - time_t old_life; - if(!tgt->flags.renewable || tgt->renew_till == NULL){ - kdc_log(context, config, 0, - "Request to renew non-renewable ticket"); - return KRB5KDC_ERR_BADOPTION; - } - old_life = tgt->endtime; - if(tgt->starttime) - old_life -= *tgt->starttime; - else - old_life -= tgt->authtime; - et->endtime = *et->starttime + old_life; - if (et->renew_till != NULL) - et->endtime = min(*et->renew_till, et->endtime); - } - - /* checks for excess flags */ - if(f.request_anonymous && !config->allow_anonymous){ - kdc_log(context, config, 0, - "Request for anonymous ticket"); - return KRB5KDC_ERR_BADOPTION; - } - return 0; -} - -static krb5_error_code -fix_transited_encoding(krb5_context context, - krb5_kdc_configuration *config, - krb5_boolean check_policy, - TransitedEncoding *tr, - EncTicketPart *et, - const char *client_realm, - const char *server_realm, - const char *tgt_realm) -{ - krb5_error_code ret = 0; - char **realms, **tmp; - int num_realms; - int i; - - switch (tr->tr_type) { - case DOMAIN_X500_COMPRESS: - break; - case 0: - /* - * Allow empty content of type 0 because that is was Microsoft - * generates in their TGT. - */ - if (tr->contents.length == 0) - break; - kdc_log(context, config, 0, - "Transited type 0 with non empty content"); - return KRB5KDC_ERR_TRTYPE_NOSUPP; - default: - kdc_log(context, config, 0, - "Unknown transited type: %u", tr->tr_type); - return KRB5KDC_ERR_TRTYPE_NOSUPP; - } - - ret = krb5_domain_x500_decode(context, - tr->contents, - &realms, - &num_realms, - client_realm, - server_realm); - if(ret){ - krb5_warn(context, ret, - "Decoding transited encoding"); - return ret; - } - if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) { - /* not us, so add the previous realm to transited set */ - if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) { - ret = ERANGE; - goto free_realms; - } - tmp = realloc(realms, (num_realms + 1) * sizeof(*realms)); - if(tmp == NULL){ - ret = ENOMEM; - goto free_realms; - } - realms = tmp; - realms[num_realms] = strdup(tgt_realm); - if(realms[num_realms] == NULL){ - ret = ENOMEM; - goto free_realms; - } - num_realms++; - } - if(num_realms == 0) { - if(strcmp(client_realm, server_realm)) - kdc_log(context, config, 0, - "cross-realm %s -> %s", client_realm, server_realm); - } else { - size_t l = 0; - char *rs; - for(i = 0; i < num_realms; i++) - l += strlen(realms[i]) + 2; - rs = malloc(l); - if(rs != NULL) { - *rs = '\0'; - for(i = 0; i < num_realms; i++) { - if(i > 0) - strlcat(rs, ", ", l); - strlcat(rs, realms[i], l); - } - kdc_log(context, config, 0, - "cross-realm %s -> %s via [%s]", - client_realm, server_realm, rs); - free(rs); - } - } - if(check_policy) { - ret = krb5_check_transited(context, client_realm, - server_realm, - realms, num_realms, NULL); - if(ret) { - krb5_warn(context, ret, "cross-realm %s -> %s", - client_realm, server_realm); - goto free_realms; - } - et->flags.transited_policy_checked = 1; - } - et->transited.tr_type = DOMAIN_X500_COMPRESS; - ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents); - if(ret) - krb5_warn(context, ret, "Encoding transited encoding"); - free_realms: - for(i = 0; i < num_realms; i++) - free(realms[i]); - free(realms); - return ret; -} - - -static krb5_error_code -tgs_make_reply(krb5_context context, - krb5_kdc_configuration *config, - KDC_REQ_BODY *b, - EncTicketPart *tgt, - EncTicketPart *adtkt, - AuthorizationData *auth_data, - krb5_ticket *tgs_ticket, - hdb_entry_ex *server, - const char *server_name, - hdb_entry_ex *client, - krb5_principal client_principal, - hdb_entry_ex *krbtgt, - EncryptionKey *tgtkey, - krb5_enctype cetype, - const char **e_text, - krb5_data *reply) -{ - KDC_REP rep; - EncKDCRepPart ek; - EncTicketPart et; - KDCOptions f = b->kdc_options; - krb5_error_code ret; - krb5_enctype etype; - Key *skey; - EncryptionKey *ekey; - AuthorizationData *new_auth_data = NULL; - - if(adtkt) { - int i; - ekey = &adtkt->key; - for(i = 0; i < b->etype.len; i++) - if (b->etype.val[i] == adtkt->key.keytype) - break; - if(i == b->etype.len) { - krb5_clear_error_string(context); - return KRB5KDC_ERR_ETYPE_NOSUPP; - } - etype = b->etype.val[i]; - }else{ - ret = find_keys(context, config, - NULL, NULL, server, server_name, - NULL, NULL, &skey, &etype, - b->etype.val, b->etype.len); - if(ret) - return ret; - ekey = &skey->key; - } - - memset(&rep, 0, sizeof(rep)); - memset(&et, 0, sizeof(et)); - memset(&ek, 0, sizeof(ek)); - - rep.pvno = 5; - rep.msg_type = krb_tgs_rep; - - et.authtime = tgt->authtime; - fix_time(&b->till); - et.endtime = min(tgt->endtime, *b->till); - ALLOC(et.starttime); - *et.starttime = kdc_time; - - ret = check_tgs_flags(context, config, b, tgt, &et); - if(ret) - goto out; - - /* We should check the transited encoding if: - 1) the request doesn't ask not to be checked - 2) globally enforcing a check - 3) principal requires checking - 4) we allow non-check per-principal, but principal isn't marked as allowing this - 5) we don't globally allow this - */ - -#define GLOBAL_FORCE_TRANSITED_CHECK \ - (config->trpolicy == TRPOLICY_ALWAYS_CHECK) -#define GLOBAL_ALLOW_PER_PRINCIPAL \ - (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL) -#define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \ - (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST) - -/* these will consult the database in future release */ -#define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0 -#define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0 - - ret = fix_transited_encoding(context, config, - !f.disable_transited_check || - GLOBAL_FORCE_TRANSITED_CHECK || - PRINCIPAL_FORCE_TRANSITED_CHECK(server) || - !((GLOBAL_ALLOW_PER_PRINCIPAL && - PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) || - GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK), - &tgt->transited, &et, - *krb5_princ_realm(context, client_principal), - *krb5_princ_realm(context, server->entry.principal), - *krb5_princ_realm(context, krbtgt->entry.principal)); - if(ret) - goto out; - - copy_Realm(krb5_princ_realm(context, server->entry.principal), - &rep.ticket.realm); - _krb5_principal2principalname(&rep.ticket.sname, server->entry.principal); - copy_Realm(&tgt->crealm, &rep.crealm); - if (f.request_anonymous) - make_anonymous_principalname (&tgt->cname); - else - copy_PrincipalName(&tgt->cname, &rep.cname); - rep.ticket.tkt_vno = 5; - - ek.caddr = et.caddr; - if(et.caddr == NULL) - et.caddr = tgt->caddr; - - { - time_t life; - life = et.endtime - *et.starttime; - if(client && client->entry.max_life) - life = min(life, *client->entry.max_life); - if(server->entry.max_life) - life = min(life, *server->entry.max_life); - et.endtime = *et.starttime + life; - } - if(f.renewable_ok && tgt->flags.renewable && - et.renew_till == NULL && et.endtime < *b->till){ - et.flags.renewable = 1; - ALLOC(et.renew_till); - *et.renew_till = *b->till; - } - if(et.renew_till){ - time_t renew; - renew = *et.renew_till - et.authtime; - if(client && client->entry.max_renew) - renew = min(renew, *client->entry.max_renew); - if(server->entry.max_renew) - renew = min(renew, *server->entry.max_renew); - *et.renew_till = et.authtime + renew; - } - - if(et.renew_till){ - *et.renew_till = min(*et.renew_till, *tgt->renew_till); - *et.starttime = min(*et.starttime, *et.renew_till); - et.endtime = min(et.endtime, *et.renew_till); - } - - *et.starttime = min(*et.starttime, et.endtime); - - if(*et.starttime == et.endtime){ - ret = KRB5KDC_ERR_NEVER_VALID; - goto out; - } - if(et.renew_till && et.endtime == *et.renew_till){ - free(et.renew_till); - et.renew_till = NULL; - et.flags.renewable = 0; - } - - et.flags.pre_authent = tgt->flags.pre_authent; - et.flags.hw_authent = tgt->flags.hw_authent; - et.flags.anonymous = tgt->flags.anonymous; - et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate; - - - krb5_generate_random_keyblock(context, etype, &et.key); - - if (server->authz_data_tgs_req) { - ret = server->authz_data_tgs_req(context, server, - client_principal, - tgs_ticket->ticket.authorization_data, - tgs_ticket->ticket.authtime, - tgtkey, - ekey, - &et.key, - &new_auth_data); - if (ret) { - new_auth_data = NULL; - } - } - - /* XXX Check enc-authorization-data */ - et.authorization_data = new_auth_data; - - et.crealm = tgt->crealm; - et.cname = tgt->cname; - - ek.key = et.key; - /* MIT must have at least one last_req */ - ek.last_req.len = 1; - ek.last_req.val = calloc(1, sizeof(*ek.last_req.val)); - ek.nonce = b->nonce; - ek.flags = et.flags; - ek.authtime = et.authtime; - ek.starttime = et.starttime; - ek.endtime = et.endtime; - ek.renew_till = et.renew_till; - ek.srealm = rep.ticket.realm; - ek.sname = rep.ticket.sname; - - log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime, - et.endtime, et.renew_till); - - /* It is somewhat unclear where the etype in the following - encryption should come from. What we have is a session - key in the passed tgt, and a list of preferred etypes - *for the new ticket*. Should we pick the best possible - etype, given the keytype in the tgt, or should we look - at the etype list here as well? What if the tgt - session key is DES3 and we want a ticket with a (say) - CAST session key. Should the DES3 etype be added to the - etype list, even if we don't want a session key with - DES3? */ - ret = encode_reply(context, config, - &rep, &et, &ek, etype, adtkt ? 0 : server->entry.kvno, - ekey, 0, &tgt->key, e_text, reply); - out: - free_TGS_REP(&rep); - free_TransitedEncoding(&et.transited); - if(et.starttime) - free(et.starttime); - if(et.renew_till) - free(et.renew_till); - free_LastReq(&ek.last_req); - memset(et.key.keyvalue.data, 0, et.key.keyvalue.length); - free_EncryptionKey(&et.key); - return ret; -} - -static krb5_error_code -tgs_check_authenticator(krb5_context context, - krb5_kdc_configuration *config, - krb5_auth_context ac, - KDC_REQ_BODY *b, - const char **e_text, - krb5_keyblock *key) -{ - krb5_authenticator auth; - size_t len; - unsigned char *buf; - size_t buf_size; - krb5_error_code ret; - krb5_crypto crypto; - - krb5_auth_con_getauthenticator(context, ac, &auth); - if(auth->cksum == NULL){ - kdc_log(context, config, 0, "No authenticator in request"); - ret = KRB5KRB_AP_ERR_INAPP_CKSUM; - goto out; - } - /* - * according to RFC1510 it doesn't need to be keyed, - * but according to the latest draft it needs to. - */ - if ( -#if 0 -!krb5_checksum_is_keyed(context, auth->cksum->cksumtype) - || -#endif - !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) { - kdc_log(context, config, 0, "Bad checksum type in authenticator: %d", - auth->cksum->cksumtype); - ret = KRB5KRB_AP_ERR_INAPP_CKSUM; - goto out; - } - - /* XXX should not re-encode this */ - ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret); - if(ret){ - kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", - krb5_get_err_text(context, ret)); - goto out; - } - if(buf_size != len) { - free(buf); - kdc_log(context, config, 0, "Internal error in ASN.1 encoder"); - *e_text = "KDC internal error"; - ret = KRB5KRB_ERR_GENERIC; - goto out; - } - ret = krb5_crypto_init(context, key, 0, &crypto); - if (ret) { - free(buf); - kdc_log(context, config, 0, "krb5_crypto_init failed: %s", - krb5_get_err_text(context, ret)); - goto out; - } - ret = krb5_verify_checksum(context, - crypto, - KRB5_KU_TGS_REQ_AUTH_CKSUM, - buf, - len, - auth->cksum); - free(buf); - krb5_crypto_destroy(context, crypto); - if(ret){ - kdc_log(context, config, 0, - "Failed to verify authenticator checksum: %s", - krb5_get_err_text(context, ret)); - } -out: - free_Authenticator(auth); - free(auth); - return ret; -} - -/* - * return the realm of a krbtgt-ticket or NULL - */ - -static Realm -get_krbtgt_realm(const PrincipalName *p) -{ - if(p->name_string.len == 2 - && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0) - return p->name_string.val[1]; - else - return NULL; -} - -static const char * -find_rpath(krb5_context context, Realm crealm, Realm srealm) -{ - const char *new_realm = krb5_config_get_string(context, - NULL, - "capaths", - crealm, - srealm, - NULL); - return new_realm; -} - - -static krb5_boolean -need_referral(krb5_context context, krb5_principal server, krb5_realm **realms) -{ - if(server->name.name_type != KRB5_NT_SRV_INST || - server->name.name_string.len != 2) - return FALSE; - - return _krb5_get_host_realm_int(context, server->name.name_string.val[1], - FALSE, realms) == 0; -} - -static krb5_error_code -tgs_rep2(krb5_context context, - krb5_kdc_configuration *config, - KDC_REQ_BODY *b, - PA_DATA *tgs_req, - krb5_data *reply, - const char *from, - const struct sockaddr *from_addr, - time_t **csec, - int **cusec) -{ - krb5_ap_req ap_req; - krb5_error_code ret; - krb5_principal princ; - krb5_auth_context ac = NULL; - krb5_ticket *ticket = NULL; - krb5_flags ap_req_options; - krb5_flags verify_ap_req_flags; - const char *e_text = NULL; - krb5_crypto crypto; - - hdb_entry_ex *krbtgt = NULL; - EncTicketPart *tgt; - Key *tkey; - krb5_enctype cetype; - krb5_principal cp = NULL; - krb5_principal sp = NULL; - AuthorizationData *auth_data = NULL; - - *csec = NULL; - *cusec = NULL; - - memset(&ap_req, 0, sizeof(ap_req)); - ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req); - if(ret){ - kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", - krb5_get_err_text(context, ret)); - goto out2; - } - - if(!get_krbtgt_realm(&ap_req.ticket.sname)){ - /* XXX check for ticket.sname == req.sname */ - kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket"); - ret = KRB5KDC_ERR_POLICY; /* ? */ - goto out2; - } - - _krb5_principalname2krb5_principal(context, &princ, - ap_req.ticket.sname, - ap_req.ticket.realm); - - ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, &krbtgt); - - if(ret) { - char *p; - ret = krb5_unparse_name(context, princ, &p); - if (ret != 0) - p = "<unparse_name failed>"; - krb5_free_principal(context, princ); - kdc_log(context, config, 0, - "Ticket-granting ticket not found in database: %s: %s", - p, krb5_get_err_text(context, ret)); - if (ret == 0) - free(p); - ret = KRB5KRB_AP_ERR_NOT_US; - goto out2; - } - - if(ap_req.ticket.enc_part.kvno && - *ap_req.ticket.enc_part.kvno != krbtgt->entry.kvno){ - char *p; - - ret = krb5_unparse_name (context, princ, &p); - krb5_free_principal(context, princ); - if (ret != 0) - p = "<unparse_name failed>"; - kdc_log(context, config, 0, - "Ticket kvno = %d, DB kvno = %d (%s)", - *ap_req.ticket.enc_part.kvno, - krbtgt->entry.kvno, - p); - if (ret == 0) - free (p); - ret = KRB5KRB_AP_ERR_BADKEYVER; - goto out2; - } - - ret = hdb_enctype2key(context, &krbtgt->entry, - ap_req.ticket.enc_part.etype, &tkey); - if(ret){ - char *str, *p; - krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str); - krb5_unparse_name(context, princ, &p); - kdc_log(context, config, 0, - "No server key with enctype %s found for %s", str, p); - free(str); - free(p); - ret = KRB5KRB_AP_ERR_BADKEYVER; - goto out2; - } - - if (b->kdc_options.validate) - verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID; - else - verify_ap_req_flags = 0; - - ret = krb5_verify_ap_req2(context, - &ac, - &ap_req, - princ, - &tkey->key, - verify_ap_req_flags, - &ap_req_options, - &ticket, - KRB5_KU_TGS_REQ_AUTH); - - krb5_free_principal(context, princ); - if(ret) { - kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", - krb5_get_err_text(context, ret)); - goto out2; - } - - { - krb5_authenticator auth; - - ret = krb5_auth_con_getauthenticator(context, ac, &auth); - if (ret == 0) { - *csec = malloc(sizeof(**csec)); - if (*csec == NULL) { - krb5_free_authenticator(context, &auth); - kdc_log(context, config, 0, "malloc failed"); - goto out2; - } - **csec = auth->ctime; - *cusec = malloc(sizeof(**cusec)); - if (*cusec == NULL) { - krb5_free_authenticator(context, &auth); - kdc_log(context, config, 0, "malloc failed"); - goto out2; - } - **csec = auth->cusec; - krb5_free_authenticator(context, &auth); - } - } - - cetype = ap_req.authenticator.etype; - - tgt = &ticket->ticket; - - ret = tgs_check_authenticator(context, config, - ac, b, &e_text, &tgt->key); - if (ret) { - krb5_auth_con_free(context, ac); - goto out2; - } - - if (b->enc_authorization_data) { - krb5_keyblock *subkey; - krb5_data ad; - ret = krb5_auth_con_getremotesubkey(context, - ac, - &subkey); - if(ret){ - krb5_auth_con_free(context, ac); - kdc_log(context, config, 0, "Failed to get remote subkey: %s", - krb5_get_err_text(context, ret)); - goto out2; - } - if(subkey == NULL){ - ret = krb5_auth_con_getkey(context, ac, &subkey); - if(ret) { - krb5_auth_con_free(context, ac); - kdc_log(context, config, 0, "Failed to get session key: %s", - krb5_get_err_text(context, ret)); - goto out2; - } - } - if(subkey == NULL){ - krb5_auth_con_free(context, ac); - kdc_log(context, config, 0, - "Failed to get key for enc-authorization-data"); - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ - goto out2; - } - ret = krb5_crypto_init(context, subkey, 0, &crypto); - if (ret) { - krb5_auth_con_free(context, ac); - kdc_log(context, config, 0, "krb5_crypto_init failed: %s", - krb5_get_err_text(context, ret)); - goto out2; - } - ret = krb5_decrypt_EncryptedData (context, - crypto, - KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, - b->enc_authorization_data, - &ad); - krb5_crypto_destroy(context, crypto); - if(ret){ - krb5_auth_con_free(context, ac); - kdc_log(context, config, 0, "Failed to decrypt enc-authorization-data"); - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ - goto out2; - } - krb5_free_keyblock(context, subkey); - ALLOC(auth_data); - ret = decode_AuthorizationData(ad.data, ad.length, auth_data, NULL); - if(ret){ - krb5_auth_con_free(context, ac); - free(auth_data); - auth_data = NULL; - kdc_log(context, config, 0, "Failed to decode authorization data"); - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ - goto out2; - } - } - - krb5_auth_con_free(context, ac); - - { - PrincipalName *s; - Realm r; - char *spn = NULL, *cpn = NULL; - hdb_entry_ex *server = NULL, *client = NULL; - int nloop = 0; - EncTicketPart adtkt; - char opt_str[128]; - - s = b->sname; - r = b->realm; - if(b->kdc_options.enc_tkt_in_skey){ - Ticket *t; - hdb_entry_ex *uu; - krb5_principal p; - Key *uukey; - - if(b->additional_tickets == NULL || - b->additional_tickets->len == 0){ - ret = KRB5KDC_ERR_BADOPTION; /* ? */ - kdc_log(context, config, 0, - "No second ticket present in request"); - goto out; - } - t = &b->additional_tickets->val[0]; - if(!get_krbtgt_realm(&t->sname)){ - kdc_log(context, config, 0, - "Additional ticket is not a ticket-granting ticket"); - ret = KRB5KDC_ERR_POLICY; - goto out2; - } - _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm); - ret = _kdc_db_fetch(context, config, p, - HDB_F_GET_CLIENT|HDB_F_GET_SERVER, &uu); - krb5_free_principal(context, p); - if(ret){ - if (ret == HDB_ERR_NOENTRY) - ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; - goto out; - } - ret = hdb_enctype2key(context, &uu->entry, - t->enc_part.etype, &uukey); - if(ret){ - _kdc_free_ent(context, uu); - ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ - goto out; - } - ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0); - _kdc_free_ent(context, uu); - if(ret) - goto out; - s = &adtkt.cname; - r = adtkt.crealm; - } - - _krb5_principalname2krb5_principal(context, &sp, *s, r); - ret = krb5_unparse_name(context, sp, &spn); - if (ret) - goto out; - _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm); - ret = krb5_unparse_name(context, cp, &cpn); - if (ret) - goto out; - unparse_flags (KDCOptions2int(b->kdc_options), - asn1_KDCOptions_units(), - opt_str, sizeof(opt_str)); - if(*opt_str) - kdc_log(context, config, 0, - "TGS-REQ %s from %s for %s [%s]", - cpn, from, spn, opt_str); - else - kdc_log(context, config, 0, - "TGS-REQ %s from %s for %s", cpn, from, spn); - server_lookup: - ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER, &server); - - if(ret){ - const char *new_rlm; - Realm req_rlm; - krb5_realm *realms; - - if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) { - if(nloop++ < 2) { - new_rlm = find_rpath(context, tgt->crealm, req_rlm); - if(new_rlm) { - kdc_log(context, config, 5, "krbtgt for realm %s not found, trying %s", - req_rlm, new_rlm); - krb5_free_principal(context, sp); - free(spn); - krb5_make_principal(context, &sp, r, - KRB5_TGS_NAME, new_rlm, NULL); - ret = krb5_unparse_name(context, sp, &spn); - if (ret) - goto out; - goto server_lookup; - } - } - } else if(need_referral(context, sp, &realms)) { - if (strcmp(realms[0], sp->realm) != 0) { - kdc_log(context, config, 5, - "Returning a referral to realm %s for " - "server %s that was not found", - realms[0], spn); - krb5_free_principal(context, sp); - free(spn); - krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, - realms[0], NULL); - ret = krb5_unparse_name(context, sp, &spn); - if (ret) - goto out; - krb5_free_host_realm(context, realms); - goto server_lookup; - } - krb5_free_host_realm(context, realms); - } - kdc_log(context, config, 0, - "Server not found in database: %s: %s", spn, - krb5_get_err_text(context, ret)); - if (ret == HDB_ERR_NOENTRY) - ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; - goto out; - } - - ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT, &client); - if(ret) - kdc_log(context, config, 1, "Client not found in database: %s: %s", - cpn, krb5_get_err_text(context, ret)); - - /* - * If the client belongs to the same realm as our krbtgt, it - * should exist in the local database. - * - * If its not the same, check the "direction" on the krbtgt, - * so its not a backward uni-directional trust. - */ - - if(strcmp(krb5_principal_get_realm(context, sp), - krb5_principal_get_comp_string(context, - krbtgt->entry.principal, 1)) == 0) { - if(ret) { - if (ret == HDB_ERR_NOENTRY) - ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; - goto out; - } - } else { - char *tpn; - ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn); - kdc_log(context, config, 0, - "Request with wrong krbtgt: %s", - (ret == 0) ? tpn : "<unknown>"); - if(ret == 0) - free(tpn); - ret = KRB5KRB_AP_ERR_NOT_US; - goto out; - - } - - ret = _kdc_check_flags(context, config, - client, cpn, - server, spn, - FALSE); - if(ret) - goto out; - - if((b->kdc_options.validate || b->kdc_options.renew) && - !krb5_principal_compare(context, - krbtgt->entry.principal, - server->entry.principal)){ - kdc_log(context, config, 0, "Inconsistent request."); - ret = KRB5KDC_ERR_SERVER_NOMATCH; - goto out; - } - - /* check for valid set of addresses */ - if(!check_addresses(context, config, tgt->caddr, from_addr)) { - ret = KRB5KRB_AP_ERR_BADADDR; - kdc_log(context, config, 0, "Request from wrong address"); - goto out; - } - - ret = tgs_make_reply(context, - config, - b, - tgt, - b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL, - auth_data, - ticket, - server, - spn, - client, - cp, - krbtgt, - &tkey->key, - cetype, - &e_text, - reply); - - out: - free(spn); - free(cpn); - - if(server) - _kdc_free_ent(context, server); - if(client) - _kdc_free_ent(context, client); - } - out2: - if(ret) { - krb5_mk_error(context, - ret, - e_text, - NULL, - cp, - sp, - NULL, - NULL, - reply); - free(*csec); - free(*cusec); - *csec = NULL; - *cusec = NULL; - } - krb5_free_principal(context, cp); - krb5_free_principal(context, sp); - if (ticket) - krb5_free_ticket(context, ticket); - free_AP_REQ(&ap_req); - if(auth_data){ - free_AuthorizationData(auth_data); - free(auth_data); - } - - if(krbtgt) - _kdc_free_ent(context, krbtgt); - - return ret; -} - - -krb5_error_code -_kdc_tgs_rep(krb5_context context, - krb5_kdc_configuration *config, - KDC_REQ *req, - krb5_data *data, - const char *from, - struct sockaddr *from_addr) -{ - krb5_error_code ret; - int i = 0; - PA_DATA *tgs_req = NULL; - time_t *csec = NULL; - int *cusec = NULL; - - if(req->padata == NULL){ - ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */ - kdc_log(context, config, 0, - "TGS-REQ from %s without PA-DATA", from); - goto out; - } - - tgs_req = find_padata(req, &i, KRB5_PADATA_TGS_REQ); - - if(tgs_req == NULL){ - ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; - - kdc_log(context, config, 0, - "TGS-REQ from %s without PA-TGS-REQ", from); - goto out; - } - ret = tgs_rep2(context, config, - &req->req_body, tgs_req, data, from, from_addr, - &csec, &cusec); -out: - if(ret && data->data == NULL){ - krb5_mk_error(context, - ret, - NULL, - NULL, - NULL, - NULL, - csec, - cusec, - data); - } - free(csec); - free(cusec); - return 0; -} diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c new file mode 100644 index 0000000000..dcf29eb6e9 --- /dev/null +++ b/source4/heimdal/kdc/krb5tgs.c @@ -0,0 +1,1781 @@ +/* + * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "kdc_locl.h" + +RCSID("$Id: krb5tgs.c,v 1.16 2006/10/22 15:54:37 lha Exp $"); + +/* + * return the realm of a krbtgt-ticket or NULL + */ + +static Realm +get_krbtgt_realm(const PrincipalName *p) +{ + if(p->name_string.len == 2 + && strcmp(p->name_string.val[0], KRB5_TGS_NAME) == 0) + return p->name_string.val[1]; + else + return NULL; +} + +/* + * The KDC might add a signed path to the ticket authorization data + * field. This is to avoid server impersonating clients and the + * request constrained delegation. + * + * This is done by storing a KRB5_AUTHDATA_IF_RELEVANT with a single + * entry of type KRB5SignedPath. + */ + +static krb5_error_code +find_KRB5SignedPath(krb5_context context, + const AuthorizationData *ad, + krb5_data *data) +{ + AuthorizationData child; + krb5_error_code ret; + int pos; + + if (ad == NULL || ad->len == 0) + return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; + + pos = ad->len - 1; + + if (ad->val[pos].ad_type != KRB5_AUTHDATA_IF_RELEVANT) + return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; + + ret = decode_AuthorizationData(ad->val[pos].ad_data.data, + ad->val[pos].ad_data.length, + &child, + NULL); + if (ret) { + krb5_set_error_string(context, "Failed to decode " + "IF_RELEVANT with %d", ret); + return ret; + } + + if (child.len != 1) { + free_AuthorizationData(&child); + return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; + } + + if (child.val[0].ad_type != KRB5_AUTHDATA_SIGNTICKET) { + free_AuthorizationData(&child); + return KRB5KDC_ERR_PADATA_TYPE_NOSUPP; + } + + if (data) + ret = der_copy_octet_string(&child.val[0].ad_data, data); + free_AuthorizationData(&child); + return ret; +} + +krb5_error_code +_kdc_add_KRB5SignedPath(krb5_context context, + krb5_kdc_configuration *config, + hdb_entry_ex *krbtgt, + krb5_enctype enctype, + krb5_const_principal server, + KRB5SignedPathPrincipals *principals, + EncTicketPart *tkt) +{ + krb5_error_code ret; + KRB5SignedPath sp; + krb5_data data; + krb5_crypto crypto = NULL; + size_t size; + + if (server && principals) { + ret = add_KRB5SignedPathPrincipals(principals, server); + if (ret) + goto out; + } + + { + KRB5SignedPathData spd; + + spd.encticket = *tkt; + spd.delegated = principals; + + ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length, + &spd, &size, ret); + if (ret) + goto out; + if (data.length != size) + krb5_abortx(context, "internal asn.1 encoder error"); + } + + { + Key *key; + ret = hdb_enctype2key(context, &krbtgt->entry, enctype, &key); + if (ret == 0) + ret = krb5_crypto_init(context, &key->key, 0, &crypto); + if (ret) { + free(data.data); + return ret; + } + } + + /* + * Fill in KRB5SignedPath + */ + + sp.etype = enctype; + sp.delegated = principals; + + ret = krb5_create_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, 0, + data.data, data.length, &sp.cksum); + krb5_crypto_destroy(context, crypto); + free(data.data); + if (ret) + goto out; + + ASN1_MALLOC_ENCODE(KRB5SignedPath, data.data, data.length, &sp, &size, ret); + free_Checksum(&sp.cksum); + if (ret) + goto out; + if (data.length != size) + krb5_abortx(context, "internal asn.1 encoder error"); + + + /* + * Add IF-RELEVANT(KRB5SignedPath) to the last slot in + * authorization data field. + */ + + if (tkt->authorization_data == NULL) { + tkt->authorization_data = calloc(1, sizeof(*tkt->authorization_data)); + if (tkt->authorization_data == NULL) { + ret = ENOMEM; + goto out; + } + } + + /* add the entry to the last element */ + { + AuthorizationData ad = { 0, NULL }; + AuthorizationDataElement ade; + + ade.ad_type = KRB5_AUTHDATA_SIGNTICKET; + ade.ad_data = data; + + ret = add_AuthorizationData(&ad, &ade); + krb5_data_free(&data); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(AuthorizationData, data.data, data.length, + &ad, &size, ret); + free_AuthorizationData(&ad); + if (ret) + return ret; + if (data.length != size) + krb5_abortx(context, "internal asn.1 encoder error"); + + ade.ad_type = KRB5_AUTHDATA_IF_RELEVANT; + ade.ad_data = data; + + ret = add_AuthorizationData(tkt->authorization_data, &ade); + krb5_data_free(&data); + if (ret) + return ret; + } + +out: + return 0; +} + +static krb5_error_code +check_KRB5SignedPath(krb5_context context, + krb5_kdc_configuration *config, + hdb_entry_ex *krbtgt, + EncTicketPart *tkt, + KRB5SignedPathPrincipals **delegated, + int require_signedpath) +{ + krb5_error_code ret; + krb5_data data; + krb5_crypto crypto = NULL; + + *delegated = NULL; + + ret = find_KRB5SignedPath(context, tkt->authorization_data, &data); + if (ret == 0) { + KRB5SignedPathData spd; + KRB5SignedPath sp; + AuthorizationData *ad; + size_t size; + + ret = decode_KRB5SignedPath(data.data, data.length, &sp, NULL); + krb5_data_free(&data); + if (ret) + return ret; + + spd.encticket = *tkt; + /* the KRB5SignedPath is the last entry */ + ad = spd.encticket.authorization_data; + if (--ad->len == 0) + spd.encticket.authorization_data = NULL; + spd.delegated = sp.delegated; + + ASN1_MALLOC_ENCODE(KRB5SignedPathData, data.data, data.length, + &spd, &size, ret); + ad->len++; + spd.encticket.authorization_data = ad; + if (ret) { + free_KRB5SignedPath(&sp); + return ret; + } + if (data.length != size) + krb5_abortx(context, "internal asn.1 encoder error"); + + { + Key *key; + ret = hdb_enctype2key(context, &krbtgt->entry, sp.etype, &key); + if (ret == 0) + ret = krb5_crypto_init(context, &key->key, 0, &crypto); + if (ret) { + free(data.data); + free_KRB5SignedPath(&sp); + return ret; + } + } + ret = krb5_verify_checksum(context, crypto, KRB5_KU_KRB5SIGNEDPATH, + data.data, data.length, + &sp.cksum); + krb5_crypto_destroy(context, crypto); + free(data.data); + if (ret) { + free_KRB5SignedPath(&sp); + return ret; + } + + if (sp.delegated) { + + *delegated = malloc(sizeof(*sp.delegated)); + if (*delegated == NULL) { + free_KRB5SignedPath(&sp); + return ENOMEM; + } + + ret = copy_KRB5SignedPathPrincipals(*delegated, sp.delegated); + if (ret) { + free_KRB5SignedPath(&sp); + free(*delegated); + *delegated = NULL; + return ret; + } + } + free_KRB5SignedPath(&sp); + + } else { + if (require_signedpath) + return KRB5KDC_ERR_BADOPTION; + } + + return 0; +} + + +/* + * + */ + +static krb5_error_code +check_tgs_flags(krb5_context context, + krb5_kdc_configuration *config, + KDC_REQ_BODY *b, const EncTicketPart *tgt, EncTicketPart *et) +{ + KDCOptions f = b->kdc_options; + + if(f.validate){ + if(!tgt->flags.invalid || tgt->starttime == NULL){ + kdc_log(context, config, 0, + "Bad request to validate ticket"); + return KRB5KDC_ERR_BADOPTION; + } + if(*tgt->starttime > kdc_time){ + kdc_log(context, config, 0, + "Early request to validate ticket"); + return KRB5KRB_AP_ERR_TKT_NYV; + } + /* XXX tkt = tgt */ + et->flags.invalid = 0; + }else if(tgt->flags.invalid){ + kdc_log(context, config, 0, + "Ticket-granting ticket has INVALID flag set"); + return KRB5KRB_AP_ERR_TKT_INVALID; + } + + if(f.forwardable){ + if(!tgt->flags.forwardable){ + kdc_log(context, config, 0, + "Bad request for forwardable ticket"); + return KRB5KDC_ERR_BADOPTION; + } + et->flags.forwardable = 1; + } + if(f.forwarded){ + if(!tgt->flags.forwardable){ + kdc_log(context, config, 0, + "Request to forward non-forwardable ticket"); + return KRB5KDC_ERR_BADOPTION; + } + et->flags.forwarded = 1; + et->caddr = b->addresses; + } + if(tgt->flags.forwarded) + et->flags.forwarded = 1; + + if(f.proxiable){ + if(!tgt->flags.proxiable){ + kdc_log(context, config, 0, + "Bad request for proxiable ticket"); + return KRB5KDC_ERR_BADOPTION; + } + et->flags.proxiable = 1; + } + if(f.proxy){ + if(!tgt->flags.proxiable){ + kdc_log(context, config, 0, + "Request to proxy non-proxiable ticket"); + return KRB5KDC_ERR_BADOPTION; + } + et->flags.proxy = 1; + et->caddr = b->addresses; + } + if(tgt->flags.proxy) + et->flags.proxy = 1; + + if(f.allow_postdate){ + if(!tgt->flags.may_postdate){ + kdc_log(context, config, 0, + "Bad request for post-datable ticket"); + return KRB5KDC_ERR_BADOPTION; + } + et->flags.may_postdate = 1; + } + if(f.postdated){ + if(!tgt->flags.may_postdate){ + kdc_log(context, config, 0, + "Bad request for postdated ticket"); + return KRB5KDC_ERR_BADOPTION; + } + if(b->from) + *et->starttime = *b->from; + et->flags.postdated = 1; + et->flags.invalid = 1; + }else if(b->from && *b->from > kdc_time + context->max_skew){ + kdc_log(context, config, 0, "Ticket cannot be postdated"); + return KRB5KDC_ERR_CANNOT_POSTDATE; + } + + if(f.renewable){ + if(!tgt->flags.renewable){ + kdc_log(context, config, 0, + "Bad request for renewable ticket"); + return KRB5KDC_ERR_BADOPTION; + } + et->flags.renewable = 1; + ALLOC(et->renew_till); + _kdc_fix_time(&b->rtime); + *et->renew_till = *b->rtime; + } + if(f.renew){ + time_t old_life; + if(!tgt->flags.renewable || tgt->renew_till == NULL){ + kdc_log(context, config, 0, + "Request to renew non-renewable ticket"); + return KRB5KDC_ERR_BADOPTION; + } + old_life = tgt->endtime; + if(tgt->starttime) + old_life -= *tgt->starttime; + else + old_life -= tgt->authtime; + et->endtime = *et->starttime + old_life; + if (et->renew_till != NULL) + et->endtime = min(*et->renew_till, et->endtime); + } + + /* checks for excess flags */ + if(f.request_anonymous && !config->allow_anonymous){ + kdc_log(context, config, 0, + "Request for anonymous ticket"); + return KRB5KDC_ERR_BADOPTION; + } + return 0; +} + +/* + * + */ + +static krb5_error_code +check_constrained_delegation(krb5_context context, + krb5_kdc_configuration *config, + hdb_entry_ex *client, + krb5_const_principal server) +{ + const HDB_Ext_Constrained_delegation_acl *acl; + krb5_error_code ret; + int i; + + ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl); + if (ret) { + krb5_clear_error_string(context); + return ret; + } + + if (acl) { + for (i = 0; i < acl->len; i++) { + if (krb5_principal_compare(context, server, &acl->val[i]) == TRUE) + return 0; + } + } + kdc_log(context, config, 0, + "Bad request for constrained delegation"); + return KRB5KDC_ERR_BADOPTION; +} + +/* + * + */ + +static krb5_error_code +verify_flags (krb5_context context, + krb5_kdc_configuration *config, + const EncTicketPart *et, + const char *pstr) +{ + if(et->endtime < kdc_time){ + kdc_log(context, config, 0, "Ticket expired (%s)", pstr); + return KRB5KRB_AP_ERR_TKT_EXPIRED; + } + if(et->flags.invalid){ + kdc_log(context, config, 0, "Ticket not valid (%s)", pstr); + return KRB5KRB_AP_ERR_TKT_NYV; + } + return 0; +} + +/* + * + */ + +static krb5_error_code +fix_transited_encoding(krb5_context context, + krb5_kdc_configuration *config, + krb5_boolean check_policy, + const TransitedEncoding *tr, + EncTicketPart *et, + const char *client_realm, + const char *server_realm, + const char *tgt_realm) +{ + krb5_error_code ret = 0; + char **realms, **tmp; + int num_realms; + int i; + + switch (tr->tr_type) { + case DOMAIN_X500_COMPRESS: + break; + case 0: + /* + * Allow empty content of type 0 because that is was Microsoft + * generates in their TGT. + */ + if (tr->contents.length == 0) + break; + kdc_log(context, config, 0, + "Transited type 0 with non empty content"); + return KRB5KDC_ERR_TRTYPE_NOSUPP; + default: + kdc_log(context, config, 0, + "Unknown transited type: %u", tr->tr_type); + return KRB5KDC_ERR_TRTYPE_NOSUPP; + } + + ret = krb5_domain_x500_decode(context, + tr->contents, + &realms, + &num_realms, + client_realm, + server_realm); + if(ret){ + krb5_warn(context, ret, + "Decoding transited encoding"); + return ret; + } + if(strcmp(client_realm, tgt_realm) && strcmp(server_realm, tgt_realm)) { + /* not us, so add the previous realm to transited set */ + if (num_realms < 0 || num_realms + 1 > UINT_MAX/sizeof(*realms)) { + ret = ERANGE; + goto free_realms; + } + tmp = realloc(realms, (num_realms + 1) * sizeof(*realms)); + if(tmp == NULL){ + ret = ENOMEM; + goto free_realms; + } + realms = tmp; + realms[num_realms] = strdup(tgt_realm); + if(realms[num_realms] == NULL){ + ret = ENOMEM; + goto free_realms; + } + num_realms++; + } + if(num_realms == 0) { + if(strcmp(client_realm, server_realm)) + kdc_log(context, config, 0, + "cross-realm %s -> %s", client_realm, server_realm); + } else { + size_t l = 0; + char *rs; + for(i = 0; i < num_realms; i++) + l += strlen(realms[i]) + 2; + rs = malloc(l); + if(rs != NULL) { + *rs = '\0'; + for(i = 0; i < num_realms; i++) { + if(i > 0) + strlcat(rs, ", ", l); + strlcat(rs, realms[i], l); + } + kdc_log(context, config, 0, + "cross-realm %s -> %s via [%s]", + client_realm, server_realm, rs); + free(rs); + } + } + if(check_policy) { + ret = krb5_check_transited(context, client_realm, + server_realm, + realms, num_realms, NULL); + if(ret) { + krb5_warn(context, ret, "cross-realm %s -> %s", + client_realm, server_realm); + goto free_realms; + } + et->flags.transited_policy_checked = 1; + } + et->transited.tr_type = DOMAIN_X500_COMPRESS; + ret = krb5_domain_x500_encode(realms, num_realms, &et->transited.contents); + if(ret) + krb5_warn(context, ret, "Encoding transited encoding"); + free_realms: + for(i = 0; i < num_realms; i++) + free(realms[i]); + free(realms); + return ret; +} + + +static krb5_error_code +tgs_make_reply(krb5_context context, + krb5_kdc_configuration *config, + KDC_REQ_BODY *b, + krb5_const_principal tgt_name, + const EncTicketPart *tgt, + const EncTicketPart *adtkt, + AuthorizationData *auth_data, + krb5_ticket *tgs_ticket, + hdb_entry_ex *server, + const char *server_name, + hdb_entry_ex *client, + krb5_principal client_principal, + hdb_entry_ex *krbtgt, + krb5_enctype krbtgt_etype, + KRB5SignedPathPrincipals *spp, + EncryptionKey *tgtkey, + const char **e_text, + krb5_data *reply) +{ + KDC_REP rep; + EncKDCRepPart ek; + EncTicketPart et; + KDCOptions f = b->kdc_options; + krb5_error_code ret; + krb5_enctype etype; + Key *skey; + const EncryptionKey *ekey; + AuthorizationData *new_auth_data = NULL; + + if(adtkt) { + int i; + ekey = &adtkt->key; + for(i = 0; i < b->etype.len; i++) + if (b->etype.val[i] == adtkt->key.keytype) + break; + if(i == b->etype.len) { + krb5_clear_error_string(context); + return KRB5KDC_ERR_ETYPE_NOSUPP; + } + etype = b->etype.val[i]; + }else{ + ret = _kdc_find_etype(context, server, b->etype.val, b->etype.len, + &skey, &etype); + if(ret) { + kdc_log(context, config, 0, + "Server (%s) has no support for etypes", server_name); + return ret; + } + ekey = &skey->key; + } + + memset(&rep, 0, sizeof(rep)); + memset(&et, 0, sizeof(et)); + memset(&ek, 0, sizeof(ek)); + + rep.pvno = 5; + rep.msg_type = krb_tgs_rep; + + et.authtime = tgt->authtime; + _kdc_fix_time(&b->till); + et.endtime = min(tgt->endtime, *b->till); + ALLOC(et.starttime); + *et.starttime = kdc_time; + + ret = check_tgs_flags(context, config, b, tgt, &et); + if(ret) + goto out; + + /* We should check the transited encoding if: + 1) the request doesn't ask not to be checked + 2) globally enforcing a check + 3) principal requires checking + 4) we allow non-check per-principal, but principal isn't marked as allowing this + 5) we don't globally allow this + */ + +#define GLOBAL_FORCE_TRANSITED_CHECK \ + (config->trpolicy == TRPOLICY_ALWAYS_CHECK) +#define GLOBAL_ALLOW_PER_PRINCIPAL \ + (config->trpolicy == TRPOLICY_ALLOW_PER_PRINCIPAL) +#define GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK \ + (config->trpolicy == TRPOLICY_ALWAYS_HONOUR_REQUEST) + +/* these will consult the database in future release */ +#define PRINCIPAL_FORCE_TRANSITED_CHECK(P) 0 +#define PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(P) 0 + + ret = fix_transited_encoding(context, config, + !f.disable_transited_check || + GLOBAL_FORCE_TRANSITED_CHECK || + PRINCIPAL_FORCE_TRANSITED_CHECK(server) || + !((GLOBAL_ALLOW_PER_PRINCIPAL && + PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) || + GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK), + &tgt->transited, &et, + *krb5_princ_realm(context, client_principal), + *krb5_princ_realm(context, server->entry.principal), + *krb5_princ_realm(context, krbtgt->entry.principal)); + if(ret) + goto out; + + copy_Realm(krb5_princ_realm(context, server->entry.principal), + &rep.ticket.realm); + _krb5_principal2principalname(&rep.ticket.sname, server->entry.principal); + copy_Realm(&tgt_name->realm, &rep.crealm); + if (f.request_anonymous) + _kdc_make_anonymous_principalname (&rep.cname); + else + copy_PrincipalName(&tgt_name->name, &rep.cname); + rep.ticket.tkt_vno = 5; + + ek.caddr = et.caddr; + if(et.caddr == NULL) + et.caddr = tgt->caddr; + + { + time_t life; + life = et.endtime - *et.starttime; + if(client && client->entry.max_life) + life = min(life, *client->entry.max_life); + if(server->entry.max_life) + life = min(life, *server->entry.max_life); + et.endtime = *et.starttime + life; + } + if(f.renewable_ok && tgt->flags.renewable && + et.renew_till == NULL && et.endtime < *b->till){ + et.flags.renewable = 1; + ALLOC(et.renew_till); + *et.renew_till = *b->till; + } + if(et.renew_till){ + time_t renew; + renew = *et.renew_till - et.authtime; + if(client && client->entry.max_renew) + renew = min(renew, *client->entry.max_renew); + if(server->entry.max_renew) + renew = min(renew, *server->entry.max_renew); + *et.renew_till = et.authtime + renew; + } + + if(et.renew_till){ + *et.renew_till = min(*et.renew_till, *tgt->renew_till); + *et.starttime = min(*et.starttime, *et.renew_till); + et.endtime = min(et.endtime, *et.renew_till); + } + + *et.starttime = min(*et.starttime, et.endtime); + + if(*et.starttime == et.endtime){ + ret = KRB5KDC_ERR_NEVER_VALID; + goto out; + } + if(et.renew_till && et.endtime == *et.renew_till){ + free(et.renew_till); + et.renew_till = NULL; + et.flags.renewable = 0; + } + + et.flags.pre_authent = tgt->flags.pre_authent; + et.flags.hw_authent = tgt->flags.hw_authent; + et.flags.anonymous = tgt->flags.anonymous; + et.flags.ok_as_delegate = server->entry.flags.ok_as_delegate; + + + krb5_generate_random_keyblock(context, etype, &et.key); + + if (server->authz_data_tgs_req) { + ret = server->authz_data_tgs_req(context, server, + client_principal, + tgs_ticket->ticket.authorization_data, + tgs_ticket->ticket.authtime, + tgtkey, + ekey, + &et.key, + &new_auth_data); + if (ret) { + new_auth_data = NULL; + } + } + + /* XXX Check enc-authorization-data */ + et.authorization_data = new_auth_data; + + et.crealm = tgt->crealm; + et.cname = tgt_name->name; + + ek.key = et.key; + /* MIT must have at least one last_req */ + ek.last_req.len = 1; + ek.last_req.val = calloc(1, sizeof(*ek.last_req.val)); + ek.nonce = b->nonce; + ek.flags = et.flags; + ek.authtime = et.authtime; + ek.starttime = et.starttime; + ek.endtime = et.endtime; + ek.renew_till = et.renew_till; + ek.srealm = rep.ticket.realm; + ek.sname = rep.ticket.sname; + + _kdc_log_timestamp(context, config, "TGS-REQ", et.authtime, et.starttime, + et.endtime, et.renew_till); + + /* Don't sign cross realm tickets, they can't be checked anyway */ + { + char *r = get_krbtgt_realm(&ek.sname); + + if (r == NULL || strcmp(r, ek.srealm) == 0) { + ret = _kdc_add_KRB5SignedPath(context, + config, + krbtgt, + krbtgt_etype, + NULL, + NULL, + &et); + if (ret) + goto out; + } + } + + /* It is somewhat unclear where the etype in the following + encryption should come from. What we have is a session + key in the passed tgt, and a list of preferred etypes + *for the new ticket*. Should we pick the best possible + etype, given the keytype in the tgt, or should we look + at the etype list here as well? What if the tgt + session key is DES3 and we want a ticket with a (say) + CAST session key. Should the DES3 etype be added to the + etype list, even if we don't want a session key with + DES3? */ + ret = _kdc_encode_reply(context, config, + &rep, &et, &ek, etype, + adtkt ? 0 : server->entry.kvno, + ekey, 0, &tgt->key, e_text, reply); +out: + free_TGS_REP(&rep); + free_TransitedEncoding(&et.transited); + if(et.starttime) + free(et.starttime); + if(et.renew_till) + free(et.renew_till); + if(et.authorization_data) { + free_AuthorizationData(et.authorization_data); + free(et.authorization_data); + } + free_LastReq(&ek.last_req); + memset(et.key.keyvalue.data, 0, et.key.keyvalue.length); + free_EncryptionKey(&et.key); + return ret; +} + +static krb5_error_code +tgs_check_authenticator(krb5_context context, + krb5_kdc_configuration *config, + krb5_auth_context ac, + KDC_REQ_BODY *b, + const char **e_text, + krb5_keyblock *key) +{ + krb5_authenticator auth; + size_t len; + unsigned char *buf; + size_t buf_size; + krb5_error_code ret; + krb5_crypto crypto; + + krb5_auth_con_getauthenticator(context, ac, &auth); + if(auth->cksum == NULL){ + kdc_log(context, config, 0, "No authenticator in request"); + ret = KRB5KRB_AP_ERR_INAPP_CKSUM; + goto out; + } + /* + * according to RFC1510 it doesn't need to be keyed, + * but according to the latest draft it needs to. + */ + if ( +#if 0 +!krb5_checksum_is_keyed(context, auth->cksum->cksumtype) + || +#endif + !krb5_checksum_is_collision_proof(context, auth->cksum->cksumtype)) { + kdc_log(context, config, 0, "Bad checksum type in authenticator: %d", + auth->cksum->cksumtype); + ret = KRB5KRB_AP_ERR_INAPP_CKSUM; + goto out; + } + + /* XXX should not re-encode this */ + ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, b, &len, ret); + if(ret){ + kdc_log(context, config, 0, "Failed to encode KDC-REQ-BODY: %s", + krb5_get_err_text(context, ret)); + goto out; + } + if(buf_size != len) { + free(buf); + kdc_log(context, config, 0, "Internal error in ASN.1 encoder"); + *e_text = "KDC internal error"; + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free(buf); + kdc_log(context, config, 0, "krb5_crypto_init failed: %s", + krb5_get_err_text(context, ret)); + goto out; + } + ret = krb5_verify_checksum(context, + crypto, + KRB5_KU_TGS_REQ_AUTH_CKSUM, + buf, + len, + auth->cksum); + free(buf); + krb5_crypto_destroy(context, crypto); + if(ret){ + kdc_log(context, config, 0, + "Failed to verify authenticator checksum: %s", + krb5_get_err_text(context, ret)); + } +out: + free_Authenticator(auth); + free(auth); + return ret; +} + +/* + * + */ + +static const char * +find_rpath(krb5_context context, Realm crealm, Realm srealm) +{ + const char *new_realm = krb5_config_get_string(context, + NULL, + "capaths", + crealm, + srealm, + NULL); + return new_realm; +} + + +static krb5_boolean +need_referral(krb5_context context, krb5_principal server, krb5_realm **realms) +{ + if(server->name.name_type != KRB5_NT_SRV_INST || + server->name.name_string.len != 2) + return FALSE; + + return _krb5_get_host_realm_int(context, server->name.name_string.val[1], + FALSE, realms) == 0; +} + +static krb5_error_code +tgs_parse_request(krb5_context context, + krb5_kdc_configuration *config, + KDC_REQ_BODY *b, + PA_DATA *tgs_req, + hdb_entry_ex **krbtgt, + krb5_enctype *krbtgt_etype, + krb5_ticket **ticket, + const char **e_text, + const char *from, + const struct sockaddr *from_addr, + time_t **csec, + int **cusec, + AuthorizationData **auth_data, + EncryptionKey **tgtkey) +{ + krb5_ap_req ap_req; + krb5_error_code ret; + krb5_principal princ; + krb5_auth_context ac = NULL; + krb5_flags ap_req_options; + krb5_flags verify_ap_req_flags; + krb5_crypto crypto; + Key *tkey; + + *auth_data = NULL; + *csec = NULL; + *cusec = NULL; + + memset(&ap_req, 0, sizeof(ap_req)); + ret = krb5_decode_ap_req(context, &tgs_req->padata_value, &ap_req); + if(ret){ + kdc_log(context, config, 0, "Failed to decode AP-REQ: %s", + krb5_get_err_text(context, ret)); + goto out; + } + + if(!get_krbtgt_realm(&ap_req.ticket.sname)){ + /* XXX check for ticket.sname == req.sname */ + kdc_log(context, config, 0, "PA-DATA is not a ticket-granting ticket"); + ret = KRB5KDC_ERR_POLICY; /* ? */ + goto out; + } + + _krb5_principalname2krb5_principal(context, + &princ, + ap_req.ticket.sname, + ap_req.ticket.realm); + + ret = _kdc_db_fetch(context, config, princ, HDB_F_GET_KRBTGT, NULL, krbtgt); + + if(ret) { + char *p; + ret = krb5_unparse_name(context, princ, &p); + if (ret != 0) + p = "<unparse_name failed>"; + krb5_free_principal(context, princ); + kdc_log(context, config, 0, + "Ticket-granting ticket not found in database: %s: %s", + p, krb5_get_err_text(context, ret)); + if (ret == 0) + free(p); + ret = KRB5KRB_AP_ERR_NOT_US; + goto out; + } + + if(ap_req.ticket.enc_part.kvno && + *ap_req.ticket.enc_part.kvno != (*krbtgt)->entry.kvno){ + char *p; + + ret = krb5_unparse_name (context, princ, &p); + krb5_free_principal(context, princ); + if (ret != 0) + p = "<unparse_name failed>"; + kdc_log(context, config, 0, + "Ticket kvno = %d, DB kvno = %d (%s)", + *ap_req.ticket.enc_part.kvno, + (*krbtgt)->entry.kvno, + p); + if (ret == 0) + free (p); + ret = KRB5KRB_AP_ERR_BADKEYVER; + goto out; + } + + *krbtgt_etype = ap_req.ticket.enc_part.etype; + + ret = hdb_enctype2key(context, &(*krbtgt)->entry, + ap_req.ticket.enc_part.etype, &tkey); + if(ret){ + char *str, *p; + krb5_enctype_to_string(context, ap_req.ticket.enc_part.etype, &str); + krb5_unparse_name(context, princ, &p); + kdc_log(context, config, 0, + "No server key with enctype %s found for %s", str, p); + free(str); + free(p); + ret = KRB5KRB_AP_ERR_BADKEYVER; + goto out; + } + + *tgtkey = &tkey->key; + + if (b->kdc_options.validate) + verify_ap_req_flags = KRB5_VERIFY_AP_REQ_IGNORE_INVALID; + else + verify_ap_req_flags = 0; + + ret = krb5_verify_ap_req2(context, + &ac, + &ap_req, + princ, + &tkey->key, + verify_ap_req_flags, + &ap_req_options, + ticket, + KRB5_KU_TGS_REQ_AUTH); + + krb5_free_principal(context, princ); + if(ret) { + kdc_log(context, config, 0, "Failed to verify AP-REQ: %s", + krb5_get_err_text(context, ret)); + goto out; + } + + { + krb5_authenticator auth; + + ret = krb5_auth_con_getauthenticator(context, ac, &auth); + if (ret == 0) { + *csec = malloc(sizeof(**csec)); + if (*csec == NULL) { + krb5_free_authenticator(context, &auth); + kdc_log(context, config, 0, "malloc failed"); + goto out; + } + **csec = auth->ctime; + *cusec = malloc(sizeof(**cusec)); + if (*cusec == NULL) { + krb5_free_authenticator(context, &auth); + kdc_log(context, config, 0, "malloc failed"); + goto out; + } + **cusec = auth->cusec; + krb5_free_authenticator(context, &auth); + } + } + + ret = tgs_check_authenticator(context, config, + ac, b, e_text, &(*ticket)->ticket.key); + if (ret) { + krb5_auth_con_free(context, ac); + goto out; + } + + if (b->enc_authorization_data) { + krb5_keyblock *subkey; + krb5_data ad; + ret = krb5_auth_con_getremotesubkey(context, + ac, + &subkey); + if(ret){ + krb5_auth_con_free(context, ac); + kdc_log(context, config, 0, "Failed to get remote subkey: %s", + krb5_get_err_text(context, ret)); + goto out; + } + if(subkey == NULL){ + ret = krb5_auth_con_getkey(context, ac, &subkey); + if(ret) { + krb5_auth_con_free(context, ac); + kdc_log(context, config, 0, "Failed to get session key: %s", + krb5_get_err_text(context, ret)); + goto out; + } + } + if(subkey == NULL){ + krb5_auth_con_free(context, ac); + kdc_log(context, config, 0, + "Failed to get key for enc-authorization-data"); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ + goto out; + } + ret = krb5_crypto_init(context, subkey, 0, &crypto); + if (ret) { + krb5_auth_con_free(context, ac); + kdc_log(context, config, 0, "krb5_crypto_init failed: %s", + krb5_get_err_text(context, ret)); + goto out; + } + ret = krb5_decrypt_EncryptedData (context, + crypto, + KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, + b->enc_authorization_data, + &ad); + krb5_crypto_destroy(context, crypto); + if(ret){ + krb5_auth_con_free(context, ac); + kdc_log(context, config, 0, + "Failed to decrypt enc-authorization-data"); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ + goto out; + } + krb5_free_keyblock(context, subkey); + ALLOC(*auth_data); + if (*auth_data == NULL) { + krb5_auth_con_free(context, ac); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ + goto out; + } + ret = decode_AuthorizationData(ad.data, ad.length, *auth_data, NULL); + if(ret){ + krb5_auth_con_free(context, ac); + free(*auth_data); + *auth_data = NULL; + kdc_log(context, config, 0, "Failed to decode authorization data"); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */ + goto out; + } + } + + krb5_auth_con_free(context, ac); + +out: + free_AP_REQ(&ap_req); + + return ret; +} + +static krb5_error_code +tgs_build_reply(krb5_context context, + krb5_kdc_configuration *config, + KDC_REQ *req, + KDC_REQ_BODY *b, + hdb_entry_ex *krbtgt, + krb5_enctype krbtgt_etype, + krb5_ticket *ticket, + krb5_data *reply, + const char *from, + const char **e_text, + AuthorizationData *auth_data, + EncryptionKey *tgtkey, + const struct sockaddr *from_addr) +{ + krb5_error_code ret; + krb5_principal cp = NULL, sp = NULL; + krb5_principal client_principal = NULL; + char *spn = NULL, *cpn = NULL; + hdb_entry_ex *server = NULL, *client = NULL; + EncTicketPart *tgt = &ticket->ticket; + KRB5SignedPathPrincipals *spp = NULL; + + PrincipalName *s; + Realm r; + int nloop = 0; + EncTicketPart adtkt; + char opt_str[128]; + int require_signedpath = 0; + + memset(&adtkt, 0, sizeof(adtkt)); + + s = b->sname; + r = b->realm; + + if(b->kdc_options.enc_tkt_in_skey){ + Ticket *t; + hdb_entry_ex *uu; + krb5_principal p; + Key *uukey; + + if(b->additional_tickets == NULL || + b->additional_tickets->len == 0){ + ret = KRB5KDC_ERR_BADOPTION; /* ? */ + kdc_log(context, config, 0, + "No second ticket present in request"); + goto out; + } + t = &b->additional_tickets->val[0]; + if(!get_krbtgt_realm(&t->sname)){ + kdc_log(context, config, 0, + "Additional ticket is not a ticket-granting ticket"); + ret = KRB5KDC_ERR_POLICY; + goto out; + } + _krb5_principalname2krb5_principal(context, &p, t->sname, t->realm); + ret = _kdc_db_fetch(context, config, p, + HDB_F_GET_CLIENT|HDB_F_GET_SERVER, + NULL, &uu); + krb5_free_principal(context, p); + if(ret){ + if (ret == HDB_ERR_NOENTRY) + ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto out; + } + ret = hdb_enctype2key(context, &uu->entry, + t->enc_part.etype, &uukey); + if(ret){ + _kdc_free_ent(context, uu); + ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ + goto out; + } + ret = krb5_decrypt_ticket(context, t, &uukey->key, &adtkt, 0); + _kdc_free_ent(context, uu); + if(ret) + goto out; + + ret = verify_flags(context, config, &adtkt, spn); + if (ret) + goto out; + + s = &adtkt.cname; + r = adtkt.crealm; + } + + _krb5_principalname2krb5_principal(context, &sp, *s, r); + ret = krb5_unparse_name(context, sp, &spn); + if (ret) + goto out; + _krb5_principalname2krb5_principal(context, &cp, tgt->cname, tgt->crealm); + ret = krb5_unparse_name(context, cp, &cpn); + if (ret) + goto out; + unparse_flags (KDCOptions2int(b->kdc_options), + asn1_KDCOptions_units(), + opt_str, sizeof(opt_str)); + if(*opt_str) + kdc_log(context, config, 0, + "TGS-REQ %s from %s for %s [%s]", + cpn, from, spn, opt_str); + else + kdc_log(context, config, 0, + "TGS-REQ %s from %s for %s", cpn, from, spn); + + /* + * Fetch server + */ + +server_lookup: + ret = _kdc_db_fetch(context, config, sp, HDB_F_GET_SERVER, NULL, &server); + + if(ret){ + const char *new_rlm; + Realm req_rlm; + krb5_realm *realms; + + if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) { + if(nloop++ < 2) { + new_rlm = find_rpath(context, tgt->crealm, req_rlm); + if(new_rlm) { + kdc_log(context, config, 5, "krbtgt for realm %s " + "not found, trying %s", + req_rlm, new_rlm); + krb5_free_principal(context, sp); + free(spn); + krb5_make_principal(context, &sp, r, + KRB5_TGS_NAME, new_rlm, NULL); + ret = krb5_unparse_name(context, sp, &spn); + if (ret) + goto out; + goto server_lookup; + } + } + } else if(need_referral(context, sp, &realms)) { + if (strcmp(realms[0], sp->realm) != 0) { + kdc_log(context, config, 5, + "Returning a referral to realm %s for " + "server %s that was not found", + realms[0], spn); + krb5_free_principal(context, sp); + free(spn); + krb5_make_principal(context, &sp, r, KRB5_TGS_NAME, + realms[0], NULL); + ret = krb5_unparse_name(context, sp, &spn); + if (ret) + goto out; + krb5_free_host_realm(context, realms); + goto server_lookup; + } + krb5_free_host_realm(context, realms); + } + kdc_log(context, config, 0, + "Server not found in database: %s: %s", spn, + krb5_get_err_text(context, ret)); + if (ret == HDB_ERR_NOENTRY) + ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto out; + } + + ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT, NULL, &client); + if(ret) { + const char *krbtgt_realm; + + /* + * If the client belongs to the same realm as our krbtgt, it + * should exist in the local database. + * + */ + + krbtgt_realm = + krb5_principal_get_comp_string(context, + krbtgt->entry.principal, 1); + + if(strcmp(krb5_principal_get_realm(context, cp), krbtgt_realm) == 0) { + if (ret == HDB_ERR_NOENTRY) + ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; + kdc_log(context, config, 1, "Client no longer in database: %s", + cpn); + goto out; + } + + kdc_log(context, config, 1, "Client not found in database: %s: %s", + cpn, krb5_get_err_text(context, ret)); + } + + /* + * Check that service is in the same realm as the krbtgt. If its + * not the same, its someone that is using a uni-directional trust + * backward. + */ + + if (strcmp(krb5_principal_get_realm(context, sp), + krb5_principal_get_comp_string(context, + krbtgt->entry.principal, + 1)) != 0) { + char *tpn; + ret = krb5_unparse_name(context, krbtgt->entry.principal, &tpn); + kdc_log(context, config, 0, + "Request with wrong krbtgt: %s", + (ret == 0) ? tpn : "<unknown>"); + if(ret == 0) + free(tpn); + ret = KRB5KRB_AP_ERR_NOT_US; + goto out; + } + + /* + * + */ + + client_principal = cp; + + if (client) { + const PA_DATA *sdata; + int i = 0; + + sdata = _kdc_find_padata(req, &i, KRB5_PADATA_S4U2SELF); + if (sdata) { + krb5_crypto crypto; + krb5_data datack; + PA_S4U2Self self; + char *selfcpn = NULL; + const char *str; + + ret = decode_PA_S4U2Self(sdata->padata_value.data, + sdata->padata_value.length, + &self, NULL); + if (ret) { + kdc_log(context, config, 0, "Failed to decode PA-S4U2Self"); + goto out; + } + + ret = _krb5_s4u2self_to_checksumdata(context, &self, &datack); + if (ret) + goto out; + + ret = krb5_crypto_init(context, &tgt->key, 0, &crypto); + if (ret) { + free_PA_S4U2Self(&self); + krb5_data_free(&datack); + kdc_log(context, config, 0, "krb5_crypto_init failed: %s", + krb5_get_err_text(context, ret)); + goto out; + } + + ret = krb5_verify_checksum(context, + crypto, + KRB5_KU_TGS_IMPERSONATE, + datack.data, + datack.length, + &self.cksum); + krb5_data_free(&datack); + krb5_crypto_destroy(context, crypto); + if (ret) { + free_PA_S4U2Self(&self); + kdc_log(context, config, 0, + "krb5_verify_checksum failed for S4U2Self: %s", + krb5_get_err_text(context, ret)); + goto out; + } + + ret = _krb5_principalname2krb5_principal(context, + &client_principal, + self.name, + self.realm); + free_PA_S4U2Self(&self); + if (ret) + goto out; + + ret = krb5_unparse_name(context, client_principal, &selfcpn); + if (ret) + goto out; + + /* + * Check that service doing the impersonating is + * requesting a ticket to it-self. + */ + if (krb5_principal_compare(context, cp, sp) != TRUE) { + kdc_log(context, config, 0, "S4U2Self: %s is not allowed " + "to impersonate some other user " + "(tried for user %s to service %s)", + cpn, selfcpn, spn); + free(selfcpn); + ret = KRB5KDC_ERR_BADOPTION; /* ? */ + goto out; + } + + /* + * If the service isn't trusted for authentication to + * delegation, remove the forward flag. + */ + + if (client->entry.flags.trusted_for_delegation) { + str = "[forwardable]"; + } else { + b->kdc_options.forwardable = 0; + str = ""; + } + kdc_log(context, config, 0, "s4u2self %s impersonating %s to " + "service %s %s", cpn, selfcpn, spn, str); + free(selfcpn); + } + } + + /* + * Constrained delegation + */ + + if (client != NULL + && b->additional_tickets != NULL + && b->additional_tickets->len != 0 + && b->kdc_options.enc_tkt_in_skey == 0) + { + Key *clientkey; + Ticket *t; + char *str; + + t = &b->additional_tickets->val[0]; + + ret = hdb_enctype2key(context, &client->entry, + t->enc_part.etype, &clientkey); + if(ret){ + ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ + goto out; + } + + ret = krb5_decrypt_ticket(context, t, &clientkey->key, &adtkt, 0); + if (ret) { + kdc_log(context, config, 0, + "failed to decrypt ticket for " + "constrained delegation from %s to %s ", spn, cpn); + goto out; + } + + /* check that ticket is valid */ + + if (adtkt.flags.forwardable == 0) { + kdc_log(context, config, 0, + "Missing forwardable flag on ticket for " + "constrained delegation from %s to %s ", spn, cpn); + ret = KRB5KDC_ERR_ETYPE_NOSUPP; /* XXX */ + goto out; + } + + ret = check_constrained_delegation(context, config, client, sp); + if (ret) { + kdc_log(context, config, 0, + "constrained delegation from %s to %s not allowed", + spn, cpn); + goto out; + } + + ret = _krb5_principalname2krb5_principal(context, + &client_principal, + adtkt.cname, + adtkt.crealm); + if (ret) + goto out; + + ret = krb5_unparse_name(context, client_principal, &str); + if (ret) + goto out; + + ret = verify_flags(context, config, &adtkt, str); + if (ret) { + free(str); + goto out; + } + + /* + * Check KRB5SignedPath in authorization data and add new entry to + * make sure servers can't fake a ticket to us. + */ + + ret = check_KRB5SignedPath(context, + config, + krbtgt, + &adtkt, + &spp, + 1); + if (ret) { + kdc_log(context, config, 0, + "KRB5SignedPath check from service %s failed " + "for delegation to %s for client %s " + "from %s failed with %s", + spn, str, cpn, from, krb5_get_err_text(context, ret)); + free(str); + goto out; + } + + kdc_log(context, config, 0, "constrained delegation for %s " + "from %s to %s", str, cpn, spn); + free(str); + + /* + * Also require that the KDC have issue the service's krbtgt + * used to do the request. + */ + require_signedpath = 1; + } + + /* + * Check flags + */ + + ret = _kdc_check_flags(context, config, + client, cpn, + server, spn, + FALSE); + if(ret) + goto out; + + if((b->kdc_options.validate || b->kdc_options.renew) && + !krb5_principal_compare(context, + krbtgt->entry.principal, + server->entry.principal)){ + kdc_log(context, config, 0, "Inconsistent request."); + ret = KRB5KDC_ERR_SERVER_NOMATCH; + goto out; + } + + /* check for valid set of addresses */ + if(!_kdc_check_addresses(context, config, tgt->caddr, from_addr)) { + ret = KRB5KRB_AP_ERR_BADADDR; + kdc_log(context, config, 0, "Request from wrong address"); + goto out; + } + + /* also check the krbtgt for signature */ + ret = check_KRB5SignedPath(context, + config, + krbtgt, + tgt, + &spp, + require_signedpath); + if (ret) { + kdc_log(context, config, 0, + "KRB5SignedPath check failed for %s (%s) from %s with %s", + spn, cpn, from, krb5_get_err_text(context, ret)); + goto out; + } + + /* + * + */ + + ret = tgs_make_reply(context, + config, + b, + client_principal, + tgt, + b->kdc_options.enc_tkt_in_skey ? &adtkt : NULL, + auth_data, + ticket, + server, + spn, + client, + cp, + krbtgt, + krbtgt_etype, + spp, + tgtkey, + e_text, + reply); + +out: + free(spn); + free(cpn); + + if(server) + _kdc_free_ent(context, server); + if(client) + _kdc_free_ent(context, client); + + if (client_principal && client_principal != cp) + krb5_free_principal(context, client_principal); + if (cp) + krb5_free_principal(context, cp); + if (sp) + krb5_free_principal(context, sp); + + free_EncTicketPart(&adtkt); + + return ret; +} + +/* + * + */ + +krb5_error_code +_kdc_tgs_rep(krb5_context context, + krb5_kdc_configuration *config, + KDC_REQ *req, + krb5_data *data, + const char *from, + struct sockaddr *from_addr) +{ + AuthorizationData *auth_data = NULL; + krb5_error_code ret; + int i = 0; + PA_DATA *tgs_req = NULL; + + hdb_entry_ex *krbtgt = NULL; + krb5_ticket *ticket = NULL; + const char *e_text = NULL; + krb5_enctype krbtgt_etype = ETYPE_NULL; + EncryptionKey *tgtkey = NULL; + + + time_t *csec = NULL; + int *cusec = NULL; + + if(req->padata == NULL){ + ret = KRB5KDC_ERR_PREAUTH_REQUIRED; /* XXX ??? */ + kdc_log(context, config, 0, + "TGS-REQ from %s without PA-DATA", from); + goto out; + } + + tgs_req = _kdc_find_padata(req, &i, KRB5_PADATA_TGS_REQ); + + if(tgs_req == NULL){ + ret = KRB5KDC_ERR_PADATA_TYPE_NOSUPP; + + kdc_log(context, config, 0, + "TGS-REQ from %s without PA-TGS-REQ", from); + goto out; + } + ret = tgs_parse_request(context, config, + &req->req_body, tgs_req, + &krbtgt, + &krbtgt_etype, + &ticket, + &e_text, + from, from_addr, + &csec, &cusec, + &auth_data, + &tgtkey); + if (ret) { + kdc_log(context, config, 0, + "Failed parsing TGS-REQ from %s", from); + goto out; + } + + ret = tgs_build_reply(context, + config, + req, + &req->req_body, + krbtgt, + krbtgt_etype, + ticket, + data, + from, + &e_text, + auth_data, + tgtkey, + from_addr); + if (ret) { + kdc_log(context, config, 0, + "Failed building TGS-REP to %s", from); + goto out; + } + +out: + if(ret && data->data == NULL){ + krb5_mk_error(context, + ret, + NULL, + NULL, + NULL, + NULL, + csec, + cusec, + data); + } + free(csec); + free(cusec); + if (ticket) + krb5_free_ticket(context, ticket); + if(krbtgt) + _kdc_free_ent(context, krbtgt); + + if (auth_data) { + free_AuthorizationData(auth_data); + free(auth_data); + } + + return 0; +} diff --git a/source4/heimdal/kdc/misc.c b/source4/heimdal/kdc/misc.c index a61c647f71..b511e1a7a8 100644 --- a/source4/heimdal/kdc/misc.c +++ b/source4/heimdal/kdc/misc.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: misc.c,v 1.29 2006/04/27 11:33:21 lha Exp $"); +RCSID("$Id: misc.c,v 1.32 2006/08/28 14:41:49 lha Exp $"); struct timeval _kdc_now; @@ -42,6 +42,7 @@ _kdc_db_fetch(krb5_context context, krb5_kdc_configuration *config, krb5_const_principal principal, unsigned flags, + HDB **db, hdb_entry_ex **h) { hdb_entry_ex *ent; @@ -66,6 +67,8 @@ _kdc_db_fetch(krb5_context context, ent); config->db[i]->hdb_close(context, config->db[i]); if(ret == 0) { + if (db) + *db = config->db[i]; *h = ent; return 0; } @@ -81,3 +84,36 @@ _kdc_free_ent(krb5_context context, hdb_entry_ex *ent) free (ent); } +/* + * Use the order list of preferred encryption types and sort the + * available keys and return the most preferred key. + */ + +krb5_error_code +_kdc_get_preferred_key(krb5_context context, + krb5_kdc_configuration *config, + hdb_entry_ex *h, + const char *name, + krb5_enctype *enctype, + Key **key) +{ + const krb5_enctype *p; + krb5_error_code ret; + int i; + + p = krb5_kerberos_enctypes(context); + + for (i = 0; p[i] != ETYPE_NULL; i++) { + if (krb5_enctype_valid(context, p[i]) != 0) + continue; + ret = hdb_enctype2key(context, &h->entry, p[i], key); + if (ret == 0) { + *enctype = p[i]; + return 0; + } + } + + krb5_set_error_string(context, "No valid kerberos key found for %s", name); + return EINVAL; +} + diff --git a/source4/heimdal/kdc/pkinit.c b/source4/heimdal/kdc/pkinit.c index c220e70ddd..e3d77c0621 100755 --- a/source4/heimdal/kdc/pkinit.c +++ b/source4/heimdal/kdc/pkinit.c @@ -33,7 +33,7 @@ #include "kdc_locl.h" -RCSID("$Id: pkinit.c,v 1.65 2006/05/06 13:22:33 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.72 2006/10/24 17:51:33 lha Exp $"); #ifdef PKINIT @@ -156,7 +156,7 @@ pk_check_pkauthenticator(krb5_context context, goto out; } - if (heim_octet_string_cmp(a->paChecksum, &checksum.checksum) != 0) { + if (der_heim_octet_string_cmp(a->paChecksum, &checksum.checksum) != 0) { krb5_clear_error_string(context); ret = KRB5KRB_ERR_GENERIC; } @@ -269,7 +269,7 @@ get_dh_param(krb5_context context, memset(&dhparam, 0, sizeof(dhparam)); - if (heim_oid_cmp(&dh_key_info->algorithm.algorithm, oid_id_dhpublicnumber())) { + if (der_heim_oid_cmp(&dh_key_info->algorithm.algorithm, oid_id_dhpublicnumber())) { krb5_set_error_string(context, "PKINIT invalid oid in clientPublicValue"); return KRB5_BADMSGTYPE; @@ -338,7 +338,7 @@ get_dh_param(krb5_context context, client_params->dh_public_key = integer_to_BN(context, "subjectPublicKey", &glue); - free_heim_integer(&glue); + der_free_heim_integer(&glue); if (client_params->dh_public_key == NULL) goto out; } @@ -426,7 +426,7 @@ _kdc_pk_rd_padata(krb5_context context, krb5_data signed_content = { 0, NULL }; const char *type = "unknown type"; const heim_oid *pa_contentType; - int have_data; + int have_data = 0; *ret_params = NULL; @@ -444,7 +444,6 @@ _kdc_pk_rd_padata(krb5_context context, if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) { PA_PK_AS_REQ_Win2k r; - int have_data; type = "PK-INIT-Win2k"; pa_contentType = oid_id_pkcs7_data(); @@ -502,7 +501,7 @@ _kdc_pk_rd_padata(krb5_context context, goto out; } - ret = heim_oid_cmp(&contentInfoOid, oid_id_pkcs7_signedData()); + ret = der_heim_oid_cmp(&contentInfoOid, oid_id_pkcs7_signedData()); if (ret != 0) { krb5_set_error_string(context, "PK-AS-REQ-Win2k invalid content " "type oid"); @@ -542,7 +541,7 @@ _kdc_pk_rd_padata(krb5_context context, } /* Signature is correct, now verify the signed message */ - if (heim_oid_cmp(&eContentType, pa_contentType)) { + if (der_heim_oid_cmp(&eContentType, pa_contentType)) { krb5_set_error_string(context, "got wrong oid for pkauthdata"); ret = KRB5_BADMSGTYPE; goto out; @@ -621,8 +620,8 @@ out: if (signed_content.data) free(signed_content.data); krb5_data_free(&eContent); - free_oid(&eContentType); - free_oid(&contentInfoOid); + der_free_oid(&eContentType); + der_free_oid(&contentInfoOid); if (ret) _kdc_pk_free_client_param(context, client_params); else @@ -657,10 +656,11 @@ pk_mk_pa_reply_enckey(krb5_context context, ContentInfo *content_info) { krb5_error_code ret; - krb5_data buf, o; + krb5_data buf, signed_data; size_t size; krb5_data_zero(&buf); + krb5_data_zero(&signed_data); switch (client_params->type) { case PKINIT_COMPAT_WIN2K: { @@ -678,6 +678,7 @@ pk_mk_pa_reply_enckey(krb5_context context, buf.data, buf.length, &kp, &size,ret); free_ReplyKeyPack_Win2k(&kp); + break; } case PKINIT_COMPAT_27: { krb5_crypto ascrypto; @@ -724,21 +725,55 @@ pk_mk_pa_reply_enckey(krb5_context context, if (buf.length != size) krb5_abortx(context, "Internal ASN.1 encoder error"); + { + hx509_query *q; + hx509_cert cert; + + ret = hx509_query_alloc(kdc_identity->hx509ctx, &q); + if (ret) + goto out; + + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); + hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); + + ret = hx509_certs_find(kdc_identity->hx509ctx, + kdc_identity->certs, + q, + &cert); + hx509_query_free(kdc_identity->hx509ctx, q); + if (ret) + goto out; + + ret = hx509_cms_create_signed_1(kdc_identity->hx509ctx, + oid_id_pkrkeydata(), + buf.data, + buf.length, + NULL, + cert, + kdc_identity->anchors, + kdc_identity->certpool, + &signed_data); + hx509_cert_free(cert); + } + + krb5_data_free(&buf); + if (ret) + goto out; + ret = hx509_cms_envelope_1(kdc_identity->hx509ctx, client_params->cert, - buf.data, buf.length, NULL, - oid_id_pkcs7_signedData(), &o); + signed_data.data, signed_data.length, NULL, + oid_id_pkcs7_signedData(), &buf); if (ret) goto out; ret = _krb5_pk_mk_ContentInfo(context, - &o, + &buf, oid_id_pkcs7_envelopedData(), content_info); - free_octet_string(&o); - - out: +out: krb5_data_free(&buf); + krb5_data_free(&signed_data); return ret; } @@ -1195,6 +1230,7 @@ _kdc_pk_check_client(krb5_context context, pk_client_params *client_params, char **subject_name) { + const HDB_Ext_PKINIT_acl *acl; krb5_error_code ret; hx509_name name; int i; @@ -1210,8 +1246,8 @@ _kdc_pk_check_client(krb5_context context, if (ret) return ret; - kdc_log(context, config, 5, - "Trying to authorize subject DN %s", + kdc_log(context, config, 0, + "Trying to authorize PK-INIT subject DN %s", *subject_name); if (config->enable_pkinit_princ_in_cert) { @@ -1225,6 +1261,28 @@ _kdc_pk_check_client(krb5_context context, } } + ret = hdb_entry_get_pkinit_acl(&client->entry, &acl); + if (ret == 0 && acl != NULL) { + /* + * Cheat here and compare the generated name with the string + * and not the reverse. + */ + for (i = 0; i < acl->len; i++) { + if (strcmp(*subject_name, acl->val[0].subject) != 0) + continue; + + /* Don't support isser and anchor checking right now */ + if (acl->val[0].issuer) + continue; + if (acl->val[0].anchor) + continue; + + kdc_log(context, config, 5, + "Found matching PK-INIT database ACL"); + return 0; + } + } + for (i = 0; i < principal_mappings.len; i++) { krb5_boolean b; @@ -1235,11 +1293,14 @@ _kdc_pk_check_client(krb5_context context, continue; if (strcmp(principal_mappings.val[i].subject, *subject_name) != 0) continue; + kdc_log(context, config, 5, + "Found matching PK-INIT FILE ACL"); return 0; } - free(*subject_name); + free(*subject_name); *subject_name = NULL; + krb5_set_error_string(context, "PKINIT no matching principals"); return KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; } @@ -1282,7 +1343,7 @@ _kdc_pk_initialize(krb5_context context, const char *user_id, const char *anchors, char **pool, - char **revoke) + char **revoke_list) { const char *file; krb5_error_code ret; @@ -1305,7 +1366,7 @@ _kdc_pk_initialize(krb5_context context, user_id, anchors, pool, - revoke, + revoke_list, NULL, NULL, NULL); diff --git a/source4/heimdal/kdc/process.c b/source4/heimdal/kdc/process.c index d0f8245bf9..ed5cb3d651 100644 --- a/source4/heimdal/kdc/process.c +++ b/source4/heimdal/kdc/process.c @@ -34,7 +34,7 @@ #include "kdc_locl.h" -RCSID("$Id: process.c,v 1.3 2005/08/12 08:25:48 lha Exp $"); +RCSID("$Id: process.c,v 1.5 2006/10/09 15:37:39 lha Exp $"); /* * handle the request in `buf, len', from `addr' (or `from' as a string), @@ -42,17 +42,19 @@ RCSID("$Id: process.c,v 1.3 2005/08/12 08:25:48 lha Exp $"); */ int -krb5_kdc_process_generic_request(krb5_context context, - krb5_kdc_configuration *config, - unsigned char *buf, - size_t len, - krb5_data *reply, - krb5_boolean *prependlength, - const char *from, - struct sockaddr *addr) +krb5_kdc_process_request(krb5_context context, + krb5_kdc_configuration *config, + unsigned char *buf, + size_t len, + krb5_data *reply, + krb5_boolean *prependlength, + const char *from, + struct sockaddr *addr, + int datagram_reply) { KDC_REQ req; Ticket ticket; + DigestREQ digestreq; krb5_error_code ret; size_t i; @@ -64,7 +66,7 @@ krb5_kdc_process_generic_request(krb5_context context, req_buffer.length = len; ret = _kdc_as_rep(context, config, &req, &req_buffer, - reply, from, addr); + reply, from, addr, datagram_reply); free_AS_REQ(&req); return ret; }else if(decode_TGS_REQ(buf, len, &req, &i) == 0){ @@ -75,6 +77,10 @@ krb5_kdc_process_generic_request(krb5_context context, ret = _kdc_do_524(context, config, &ticket, reply, from, addr); free_Ticket(&ticket); return ret; + }else if(decode_DigestREQ(buf, len, &digestreq, &i) == 0){ + ret = _kdc_do_digest(context, config, &digestreq, reply, from, addr); + free_DigestREQ(&digestreq); + return ret; } else if(_kdc_maybe_version4(buf, len)){ *prependlength = FALSE; /* elbitapmoc sdrawkcab XXX */ _kdc_do_version4(context, config, buf, len, reply, from, @@ -103,7 +109,8 @@ krb5_kdc_process_krb5_request(krb5_context context, size_t len, krb5_data *reply, const char *from, - struct sockaddr *addr) + struct sockaddr *addr, + int datagram_reply) { KDC_REQ req; krb5_error_code ret; @@ -117,7 +124,7 @@ krb5_kdc_process_krb5_request(krb5_context context, req_buffer.length = len; ret = _kdc_as_rep(context, config, &req, &req_buffer, - reply, from, addr); + reply, from, addr, datagram_reply); free_AS_REQ(&req); return ret; }else if(decode_TGS_REQ(buf, len, &req, &i) == 0){ diff --git a/source4/heimdal/lib/asn1/CMS.asn1 b/source4/heimdal/lib/asn1/CMS.asn1 index 78873761b6..ce43c2cd02 100644 --- a/source4/heimdal/lib/asn1/CMS.asn1 +++ b/source4/heimdal/lib/asn1/CMS.asn1 @@ -1,5 +1,5 @@ -- From RFC 3369 -- --- $Id: CMS.asn1,v 1.4 2006/04/15 10:53:25 lha Exp $ -- +-- $Id: CMS.asn1,v 1.5 2006/09/07 12:20:42 lha Exp $ -- CMS DEFINITIONS ::= BEGIN @@ -17,7 +17,13 @@ id-pkcs7-signedAndEnvelopedData OBJECT IDENTIFIER ::= { id-pkcs7 4 } id-pkcs7-digestedData OBJECT IDENTIFIER ::= { id-pkcs7 5 } id-pkcs7-encryptedData OBJECT IDENTIFIER ::= { id-pkcs7 6 } -CMSVersion ::= INTEGER { v0(0), v1(1), v2(2), v3(3), v4(4) } +CMSVersion ::= INTEGER { + CMSVersion_v0(0), + CMSVersion_v1(1), + CMSVersion_v2(2), + CMSVersion_v3(3), + CMSVersion_v4(4) +} DigestAlgorithmIdentifier ::= AlgorithmIdentifier DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier diff --git a/source4/heimdal/lib/asn1/asn1-common.h b/source4/heimdal/lib/asn1/asn1-common.h index 01411b384a..ab06ae79dd 100644 --- a/source4/heimdal/lib/asn1/asn1-common.h +++ b/source4/heimdal/lib/asn1/asn1-common.h @@ -1,4 +1,4 @@ -/* $Id: asn1-common.h,v 1.5 2005/07/12 06:27:14 lha Exp $ */ +/* $Id: asn1-common.h,v 1.6 2006/10/14 05:09:47 lha Exp $ */ #include <stddef.h> #include <time.h> @@ -43,6 +43,9 @@ typedef struct heim_bit_string { void *data; } heim_bit_string; +typedef struct heim_octet_string heim_any; +typedef struct heim_octet_string heim_any_set; + #define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \ do { \ (BL) = length_##T((S)); \ diff --git a/source4/heimdal/lib/asn1/der-protos.h b/source4/heimdal/lib/asn1/der-protos.h new file mode 100644 index 0000000000..3aee392c96 --- /dev/null +++ b/source4/heimdal/lib/asn1/der-protos.h @@ -0,0 +1,542 @@ +/* This is a generated file */ +#ifndef __der_protos_h__ +#define __der_protos_h__ + +#include <stdarg.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int +copy_heim_any ( + const heim_any */*from*/, + heim_any */*to*/); + +int +copy_heim_any_set ( + const heim_any_set */*from*/, + heim_any_set */*to*/); + +int +decode_heim_any ( + const unsigned char */*p*/, + size_t /*len*/, + heim_any */*data*/, + size_t */*size*/); + +int +decode_heim_any_set ( + const unsigned char */*p*/, + size_t /*len*/, + heim_any_set */*data*/, + size_t */*size*/); + +int +der_copy_bit_string ( + const heim_bit_string */*from*/, + heim_bit_string */*to*/); + +int +der_copy_bmp_string ( + const heim_bmp_string */*from*/, + heim_bmp_string */*to*/); + +int +der_copy_general_string ( + const heim_general_string */*from*/, + heim_general_string */*to*/); + +int +der_copy_heim_integer ( + const heim_integer */*from*/, + heim_integer */*to*/); + +int +der_copy_ia5_string ( + const heim_printable_string */*from*/, + heim_printable_string */*to*/); + +int +der_copy_octet_string ( + const heim_octet_string */*from*/, + heim_octet_string */*to*/); + +int +der_copy_oid ( + const heim_oid */*from*/, + heim_oid */*to*/); + +int +der_copy_printable_string ( + const heim_printable_string */*from*/, + heim_printable_string */*to*/); + +int +der_copy_universal_string ( + const heim_universal_string */*from*/, + heim_universal_string */*to*/); + +int +der_copy_utf8string ( + const heim_utf8_string */*from*/, + heim_utf8_string */*to*/); + +void +der_free_bit_string (heim_bit_string */*k*/); + +void +der_free_bmp_string (heim_bmp_string */*k*/); + +void +der_free_general_string (heim_general_string */*str*/); + +void +der_free_heim_integer (heim_integer */*k*/); + +void +der_free_ia5_string (heim_ia5_string */*str*/); + +void +der_free_octet_string (heim_octet_string */*k*/); + +void +der_free_oid (heim_oid */*k*/); + +void +der_free_printable_string (heim_printable_string */*str*/); + +void +der_free_universal_string (heim_universal_string */*k*/); + +void +der_free_utf8string (heim_utf8_string */*str*/); + +int +der_get_bit_string ( + const unsigned char */*p*/, + size_t /*len*/, + heim_bit_string */*data*/, + size_t */*size*/); + +int +der_get_bmp_string ( + const unsigned char */*p*/, + size_t /*len*/, + heim_bmp_string */*data*/, + size_t */*size*/); + +int +der_get_boolean ( + const unsigned char */*p*/, + size_t /*len*/, + int */*data*/, + size_t */*size*/); + +const char * +der_get_class_name (unsigned /*num*/); + +int +der_get_class_num (const char */*name*/); + +int +der_get_general_string ( + const unsigned char */*p*/, + size_t /*len*/, + heim_general_string */*str*/, + size_t */*size*/); + +int +der_get_generalized_time ( + const unsigned char */*p*/, + size_t /*len*/, + time_t */*data*/, + size_t */*size*/); + +int +der_get_heim_integer ( + const unsigned char */*p*/, + size_t /*len*/, + heim_integer */*data*/, + size_t */*size*/); + +int +der_get_ia5_string ( + const unsigned char */*p*/, + size_t /*len*/, + heim_ia5_string */*str*/, + size_t */*size*/); + +int +der_get_integer ( + const unsigned char */*p*/, + size_t /*len*/, + int */*ret*/, + size_t */*size*/); + +int +der_get_length ( + const unsigned char */*p*/, + size_t /*len*/, + size_t */*val*/, + size_t */*size*/); + +int +der_get_octet_string ( + const unsigned char */*p*/, + size_t /*len*/, + heim_octet_string */*data*/, + size_t */*size*/); + +int +der_get_oid ( + const unsigned char */*p*/, + size_t /*len*/, + heim_oid */*data*/, + size_t */*size*/); + +int +der_get_printable_string ( + const unsigned char */*p*/, + size_t /*len*/, + heim_printable_string */*str*/, + size_t */*size*/); + +int +der_get_tag ( + const unsigned char */*p*/, + size_t /*len*/, + Der_class */*class*/, + Der_type */*type*/, + unsigned int */*tag*/, + size_t */*size*/); + +const char * +der_get_tag_name (unsigned /*num*/); + +int +der_get_tag_num (const char */*name*/); + +const char * +der_get_type_name (unsigned /*num*/); + +int +der_get_type_num (const char */*name*/); + +int +der_get_universal_string ( + const unsigned char */*p*/, + size_t /*len*/, + heim_universal_string */*data*/, + size_t */*size*/); + +int +der_get_unsigned ( + const unsigned char */*p*/, + size_t /*len*/, + unsigned */*ret*/, + size_t */*size*/); + +int +der_get_utctime ( + const unsigned char */*p*/, + size_t /*len*/, + time_t */*data*/, + size_t */*size*/); + +int +der_get_utf8string ( + const unsigned char */*p*/, + size_t /*len*/, + heim_utf8_string */*str*/, + size_t */*size*/); + +int +der_heim_bit_string_cmp ( + const heim_bit_string */*p*/, + const heim_bit_string */*q*/); + +int +der_heim_bmp_string_cmp ( + const heim_bmp_string */*p*/, + const heim_bmp_string */*q*/); + +int +der_heim_integer_cmp ( + const heim_integer */*p*/, + const heim_integer */*q*/); + +int +der_heim_octet_string_cmp ( + const heim_octet_string */*p*/, + const heim_octet_string */*q*/); + +int +der_heim_oid_cmp ( + const heim_oid */*p*/, + const heim_oid */*q*/); + +int +der_heim_universal_string_cmp ( + const heim_universal_string */*p*/, + const heim_universal_string */*q*/); + +size_t +der_length_bit_string (const heim_bit_string */*k*/); + +size_t +der_length_bmp_string (const heim_bmp_string */*data*/); + +size_t +der_length_boolean (const int */*k*/); + +size_t +der_length_enumerated (const unsigned */*data*/); + +size_t +der_length_general_string (const heim_general_string */*data*/); + +size_t +der_length_generalized_time (const time_t */*t*/); + +size_t +der_length_heim_integer (const heim_integer */*k*/); + +size_t +der_length_ia5_string (const heim_ia5_string */*data*/); + +size_t +der_length_integer (const int */*data*/); + +size_t +der_length_len (size_t /*len*/); + +size_t +der_length_octet_string (const heim_octet_string */*k*/); + +size_t +der_length_oid (const heim_oid */*k*/); + +size_t +der_length_printable_string (const heim_printable_string */*data*/); + +size_t +der_length_universal_string (const heim_universal_string */*data*/); + +size_t +der_length_unsigned (const unsigned */*data*/); + +size_t +der_length_utctime (const time_t */*t*/); + +size_t +der_length_utf8string (const heim_utf8_string */*data*/); + +int +der_match_tag ( + const unsigned char */*p*/, + size_t /*len*/, + Der_class /*class*/, + Der_type /*type*/, + unsigned int /*tag*/, + size_t */*size*/); + +int +der_match_tag_and_length ( + const unsigned char */*p*/, + size_t /*len*/, + Der_class /*class*/, + Der_type /*type*/, + unsigned int /*tag*/, + size_t */*length_ret*/, + size_t */*size*/); + +int +der_parse_heim_oid ( + const char */*str*/, + const char */*sep*/, + heim_oid */*data*/); + +int +der_parse_hex_heim_integer ( + const char */*p*/, + heim_integer */*data*/); + +int +der_print_heim_oid ( + const heim_oid */*oid*/, + char /*delim*/, + char **/*str*/); + +int +der_print_hex_heim_integer ( + const heim_integer */*data*/, + char **/*p*/); + +int +der_put_bit_string ( + unsigned char */*p*/, + size_t /*len*/, + const heim_bit_string */*data*/, + size_t */*size*/); + +int +der_put_bmp_string ( + unsigned char */*p*/, + size_t /*len*/, + const heim_bmp_string */*data*/, + size_t */*size*/); + +int +der_put_boolean ( + unsigned char */*p*/, + size_t /*len*/, + const int */*data*/, + size_t */*size*/); + +int +der_put_general_string ( + unsigned char */*p*/, + size_t /*len*/, + const heim_general_string */*str*/, + size_t */*size*/); + +int +der_put_generalized_time ( + unsigned char */*p*/, + size_t /*len*/, + const time_t */*data*/, + size_t */*size*/); + +int +der_put_heim_integer ( + unsigned char */*p*/, + size_t /*len*/, + const heim_integer */*data*/, + size_t */*size*/); + +int +der_put_ia5_string ( + unsigned char */*p*/, + size_t /*len*/, + const heim_ia5_string */*str*/, + size_t */*size*/); + +int +der_put_integer ( + unsigned char */*p*/, + size_t /*len*/, + const int */*v*/, + size_t */*size*/); + +int +der_put_length ( + unsigned char */*p*/, + size_t /*len*/, + size_t /*val*/, + size_t */*size*/); + +int +der_put_length_and_tag ( + unsigned char */*p*/, + size_t /*len*/, + size_t /*len_val*/, + Der_class /*class*/, + Der_type /*type*/, + unsigned int /*tag*/, + size_t */*size*/); + +int +der_put_octet_string ( + unsigned char */*p*/, + size_t /*len*/, + const heim_octet_string */*data*/, + size_t */*size*/); + +int +der_put_oid ( + unsigned char */*p*/, + size_t /*len*/, + const heim_oid */*data*/, + size_t */*size*/); + +int +der_put_printable_string ( + unsigned char */*p*/, + size_t /*len*/, + const heim_printable_string */*str*/, + size_t */*size*/); + +int +der_put_tag ( + unsigned char */*p*/, + size_t /*len*/, + Der_class /*class*/, + Der_type /*type*/, + unsigned int /*tag*/, + size_t */*size*/); + +int +der_put_universal_string ( + unsigned char */*p*/, + size_t /*len*/, + const heim_universal_string */*data*/, + size_t */*size*/); + +int +der_put_unsigned ( + unsigned char */*p*/, + size_t /*len*/, + const unsigned */*v*/, + size_t */*size*/); + +int +der_put_utctime ( + unsigned char */*p*/, + size_t /*len*/, + const time_t */*data*/, + size_t */*size*/); + +int +der_put_utf8string ( + unsigned char */*p*/, + size_t /*len*/, + const heim_utf8_string */*str*/, + size_t */*size*/); + +int +encode_heim_any ( + unsigned char */*p*/, + size_t /*len*/, + const heim_any */*data*/, + size_t */*size*/); + +int +encode_heim_any_set ( + unsigned char */*p*/, + size_t /*len*/, + const heim_any_set */*data*/, + size_t */*size*/); + +void +free_heim_any (heim_any */*data*/); + +void +free_heim_any_set (heim_any_set */*data*/); + +int +heim_any_cmp ( + const heim_any_set */*p*/, + const heim_any_set */*q*/); + +size_t +length_heim_any (const heim_any */*data*/); + +size_t +length_heim_any_set (const heim_any */*data*/); + +#ifdef __cplusplus +} +#endif + +#endif /* __der_protos_h__ */ diff --git a/source4/heimdal/lib/asn1/der.h b/source4/heimdal/lib/asn1/der.h index b9c2b47079..b0170e35fe 100644 --- a/source4/heimdal/lib/asn1/der.h +++ b/source4/heimdal/lib/asn1/der.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: der.h,v 1.32 2006/01/30 15:25:25 lha Exp $ */ +/* $Id: der.h,v 1.36 2006/10/14 05:16:08 lha Exp $ */ #ifndef __DER_H__ #define __DER_H__ @@ -83,164 +83,21 @@ enum { #define ASN1_INDEFINITE 0xdce0deed -typedef struct asn1_der_time_t { +typedef struct heim_der_time_t { time_t dt_sec; unsigned long dt_nsec; -} asn1_der_time_t; +} heim_der_time_t; -typedef struct asn1_ber_time_t { +typedef struct heim_ber_time_t { time_t bt_sec; unsigned bt_nsec; int bt_zone; -} asn1_ber_time_t; +} heim_ber_time_t; -int der_get_unsigned (const unsigned char *p, size_t len, - unsigned *ret, size_t *size); -int der_get_integer (const unsigned char *p, size_t len, - int *ret, size_t *size); -int der_get_heim_integer (const unsigned char *p, size_t len, - heim_integer *ret, size_t *size); -int der_get_boolean(const unsigned char *p, size_t len, - int *data, size_t *size); -int der_get_length (const unsigned char *p, size_t len, - size_t *val, size_t *size); -int der_get_general_string (const unsigned char *p, size_t len, - heim_general_string *str, size_t *size); -int der_get_utf8string (const unsigned char *p, size_t len, - heim_utf8_string *str, size_t *size); -int der_get_universal_string (const unsigned char *p, size_t len, - heim_universal_string *str, size_t *size); -int der_get_bmp_string (const unsigned char *p, size_t len, - heim_bmp_string *str, size_t *size); -int der_get_printable_string (const unsigned char *p, size_t len, - heim_printable_string *str, size_t *size); -int der_get_ia5_string (const unsigned char *p, size_t len, - heim_ia5_string *str, size_t *size); -int der_get_octet_string (const unsigned char *p, size_t len, - heim_octet_string *data, size_t *size); -int der_get_generalized_time (const unsigned char *p, size_t len, - time_t *data, size_t *size); -int der_get_generalized_time_der (const unsigned char *p, size_t len, - asn1_der_time_t *data, size_t *size); -int der_get_generalized_time_ber (const unsigned char *p, size_t len, - asn1_ber_time_t *data, size_t *size); -int der_get_utctime (const unsigned char *p, size_t len, - time_t *data, size_t *size); -int der_get_oid (const unsigned char *p, size_t len, - heim_oid *data, size_t *size); -int der_get_bit_string (const unsigned char *p, size_t len, - heim_bit_string *data, size_t *size); -int der_get_tag (const unsigned char *p, size_t len, - Der_class *class, Der_type *type, - unsigned int *tag, size_t *size); - -int der_match_tag (const unsigned char *p, size_t len, - Der_class class, Der_type type, - unsigned int tag, size_t *size); -int der_match_tag_and_length (const unsigned char *p, size_t len, - Der_class class, Der_type type, unsigned int tag, - size_t *length_ret, size_t *size); - -int der_put_unsigned (unsigned char *p, size_t len, const unsigned *val, size_t*); -int der_put_integer (unsigned char *p, size_t len, const int *val, size_t*); -int der_put_heim_integer (unsigned char *p, size_t len, - const heim_integer *val, size_t*); -int der_put_boolean (unsigned char *p, size_t len, const int *val, size_t*); - -int der_put_length (unsigned char *p, size_t len, size_t val, size_t*); -int der_put_general_string (unsigned char *p, size_t len, - const heim_general_string *str, size_t*); -int der_put_utf8string (unsigned char *p, size_t len, - const heim_utf8_string *str, size_t*); -int der_put_universal_string (unsigned char *p, size_t len, - const heim_universal_string *str, size_t*); -int der_put_bmp_string (unsigned char *p, size_t len, - const heim_bmp_string *str, size_t*); -int der_put_printable_string (unsigned char *p, size_t len, - const heim_printable_string *str, size_t*); -int der_put_ia5_string (unsigned char *p, size_t len, - const heim_ia5_string *str, size_t*); -int der_put_octet_string (unsigned char *p, size_t len, - const heim_octet_string *data, size_t*); -int der_put_generalized_time (unsigned char *p, size_t len, - const time_t *data, size_t *size); -int der_put_utctime (unsigned char *p, size_t len, - const time_t *data, size_t *size); -int der_put_oid (unsigned char *p, size_t len, - const heim_oid *data, size_t *size); -int der_put_bit_string (unsigned char *p, size_t len, - const heim_bit_string *data, size_t *size); -int der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, - unsigned int tag, size_t*); -int der_put_length_and_tag (unsigned char*, size_t, size_t, - Der_class, Der_type, unsigned int, size_t*); - -void free_integer (int *num); -void free_heim_integer (heim_integer *num); -void free_octet_string (heim_octet_string *k); -void free_general_string (heim_general_string *str); -void free_octet_string (heim_octet_string *k); -void free_oid (heim_oid *k); -void free_bit_string (heim_bit_string *k); -void free_generalized_time (time_t *t); -void free_utctime (time_t *t); -void free_utf8string (heim_utf8_string*); -void free_printable_string (heim_printable_string*); -void free_ia5_string (heim_ia5_string*); -void free_universal_string (heim_universal_string*); -void free_bmp_string (heim_bmp_string*); - -size_t length_len (size_t len); -size_t length_integer (const int *data); -size_t length_heim_integer (const heim_integer *data); -size_t length_unsigned (const unsigned *data); -size_t length_enumerated (const unsigned *data); -size_t length_general_string (const heim_general_string *data); -size_t length_octet_string (const heim_octet_string *k); -size_t length_oid (const heim_oid *k); -size_t length_bit_string (const heim_bit_string *k); -size_t length_generalized_time (const time_t *t); -size_t length_utctime (const time_t *t); -size_t length_utf8string (const heim_utf8_string*); -size_t length_printable_string (const heim_printable_string*); -size_t length_ia5_string (const heim_ia5_string*); -size_t length_bmp_string (const heim_bmp_string*); -size_t length_universal_string (const heim_universal_string*); -size_t length_boolean (const int*); - -int copy_heim_integer (const heim_integer *, heim_integer *); -int copy_general_string (const heim_general_string *, heim_general_string *); -int copy_octet_string (const heim_octet_string *, heim_octet_string *); -int copy_oid (const heim_oid *from, heim_oid *to); -int copy_bit_string (const heim_bit_string *from, heim_bit_string *to); -int copy_utf8string (const heim_utf8_string*, heim_utf8_string*); -int copy_printable_string (const heim_printable_string*,heim_printable_string*); -int copy_ia5_string (const heim_ia5_string*,heim_ia5_string*); -int copy_universal_string(const heim_universal_string*,heim_universal_string*); -int copy_bmp_string (const heim_bmp_string*,heim_bmp_string*); - -int heim_oid_cmp(const heim_oid *, const heim_oid *); -int heim_octet_string_cmp(const heim_octet_string *,const heim_octet_string *); -int heim_bit_string_cmp(const heim_bit_string *, const heim_bit_string *); -int heim_integer_cmp(const heim_integer *, const heim_integer *); -int heim_bmp_string_cmp(const heim_bmp_string *, const heim_bmp_string *); -int heim_universal_string_cmp(const heim_universal_string *, - const heim_universal_string *); - -int der_parse_oid(const char *, heim_oid *); +#include <der-protos.h> int _heim_fix_dce(size_t reallen, size_t *len); int _heim_der_set_sort(const void *, const void *); int _heim_time2generalizedtime (time_t, heim_octet_string *, int); -const char * der_get_class_name(unsigned); -int der_get_class_num(const char *); -const char * der_get_type_name(unsigned); -int der_get_type_num(const char *); -const char * der_get_tag_name(unsigned); -int der_get_tag_num(const char *); - -int der_parse_hex_heim_integer(const char *, heim_integer *); -int der_print_hex_heim_integer(const heim_integer *, char **); - #endif /* __DER_H__ */ diff --git a/source4/heimdal/lib/asn1/der_cmp.c b/source4/heimdal/lib/asn1/der_cmp.c index 2471312ba8..f27f03c02b 100755 --- a/source4/heimdal/lib/asn1/der_cmp.c +++ b/source4/heimdal/lib/asn1/der_cmp.c @@ -34,7 +34,7 @@ #include "der_locl.h" int -heim_oid_cmp(const heim_oid *p, const heim_oid *q) +der_heim_oid_cmp(const heim_oid *p, const heim_oid *q) { if (p->length != q->length) return p->length - q->length; @@ -44,7 +44,8 @@ heim_oid_cmp(const heim_oid *p, const heim_oid *q) } int -heim_octet_string_cmp(const heim_octet_string *p, const heim_octet_string *q) +der_heim_octet_string_cmp(const heim_octet_string *p, + const heim_octet_string *q) { if (p->length != q->length) return p->length - q->length; @@ -52,7 +53,8 @@ heim_octet_string_cmp(const heim_octet_string *p, const heim_octet_string *q) } int -heim_bit_string_cmp(const heim_bit_string *p, const heim_bit_string *q) +der_heim_bit_string_cmp(const heim_bit_string *p, + const heim_bit_string *q) { int i, r1, r2; if (p->length != q->length) @@ -72,7 +74,8 @@ heim_bit_string_cmp(const heim_bit_string *p, const heim_bit_string *q) } int -heim_integer_cmp(const heim_integer *p, const heim_integer *q) +der_heim_integer_cmp(const heim_integer *p, + const heim_integer *q) { if (p->negative != q->negative) return q->negative - p->negative; @@ -82,7 +85,7 @@ heim_integer_cmp(const heim_integer *p, const heim_integer *q) } int -heim_bmp_string_cmp(const heim_bmp_string *p, const heim_bmp_string *q) +der_heim_bmp_string_cmp(const heim_bmp_string *p, const heim_bmp_string *q) { if (p->length != q->length) return p->length - q->length; @@ -90,8 +93,8 @@ heim_bmp_string_cmp(const heim_bmp_string *p, const heim_bmp_string *q) } int -heim_universal_string_cmp(const heim_universal_string *p, - const heim_universal_string *q) +der_heim_universal_string_cmp(const heim_universal_string *p, + const heim_universal_string *q) { if (p->length != q->length) return p->length - q->length; diff --git a/source4/heimdal/lib/asn1/der_copy.c b/source4/heimdal/lib/asn1/der_copy.c index e0443eed39..96eea9c6d7 100644 --- a/source4/heimdal/lib/asn1/der_copy.c +++ b/source4/heimdal/lib/asn1/der_copy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,10 +33,11 @@ #include "der_locl.h" -RCSID("$Id: der_copy.c,v 1.14 2006/01/04 23:41:29 lha Exp $"); +RCSID("$Id: der_copy.c,v 1.16 2006/10/14 05:30:02 lha Exp $"); int -copy_general_string (const heim_general_string *from, heim_general_string *to) +der_copy_general_string (const heim_general_string *from, + heim_general_string *to) { *to = strdup(*from); if(*to == NULL) @@ -45,27 +46,27 @@ copy_general_string (const heim_general_string *from, heim_general_string *to) } int -copy_utf8string (const heim_utf8_string *from, heim_utf8_string *to) +der_copy_utf8string (const heim_utf8_string *from, heim_utf8_string *to) { - return copy_general_string(from, to); + return der_copy_general_string(from, to); } int -copy_printable_string (const heim_printable_string *from, +der_copy_printable_string (const heim_printable_string *from, heim_printable_string *to) { - return copy_general_string(from, to); + return der_copy_general_string(from, to); } int -copy_ia5_string (const heim_printable_string *from, - heim_printable_string *to) +der_copy_ia5_string (const heim_printable_string *from, + heim_printable_string *to) { - return copy_general_string(from, to); + return der_copy_general_string(from, to); } int -copy_bmp_string (const heim_bmp_string *from, heim_bmp_string *to) +der_copy_bmp_string (const heim_bmp_string *from, heim_bmp_string *to) { to->length = from->length; to->data = malloc(to->length * sizeof(to->data[0])); @@ -76,8 +77,8 @@ copy_bmp_string (const heim_bmp_string *from, heim_bmp_string *to) } int -copy_universal_string (const heim_universal_string *from, - heim_universal_string *to) +der_copy_universal_string (const heim_universal_string *from, + heim_universal_string *to) { to->length = from->length; to->data = malloc(to->length * sizeof(to->data[0])); @@ -88,7 +89,7 @@ copy_universal_string (const heim_universal_string *from, } int -copy_octet_string (const heim_octet_string *from, heim_octet_string *to) +der_copy_octet_string (const heim_octet_string *from, heim_octet_string *to) { to->length = from->length; to->data = malloc(to->length); @@ -99,7 +100,7 @@ copy_octet_string (const heim_octet_string *from, heim_octet_string *to) } int -copy_heim_integer (const heim_integer *from, heim_integer *to) +der_copy_heim_integer (const heim_integer *from, heim_integer *to) { to->length = from->length; to->data = malloc(to->length); @@ -111,7 +112,7 @@ copy_heim_integer (const heim_integer *from, heim_integer *to) } int -copy_oid (const heim_oid *from, heim_oid *to) +der_copy_oid (const heim_oid *from, heim_oid *to) { to->length = from->length; to->components = malloc(to->length * sizeof(*to->components)); @@ -123,7 +124,7 @@ copy_oid (const heim_oid *from, heim_oid *to) } int -copy_bit_string (const heim_bit_string *from, heim_bit_string *to) +der_copy_bit_string (const heim_bit_string *from, heim_bit_string *to) { size_t len; diff --git a/source4/heimdal/lib/asn1/der_format.c b/source4/heimdal/lib/asn1/der_format.c index 44e39b46c5..9655269356 100644 --- a/source4/heimdal/lib/asn1/der_format.c +++ b/source4/heimdal/lib/asn1/der_format.c @@ -34,7 +34,7 @@ #include "der_locl.h" #include <hex.h> -RCSID("$Id: der_format.c,v 1.2 2006/01/16 23:01:11 lha Exp $"); +RCSID("$Id: der_format.c,v 1.6 2006/10/21 18:24:15 lha Exp $"); int der_parse_hex_heim_integer (const char *p, heim_integer *data) @@ -73,13 +73,13 @@ der_parse_hex_heim_integer (const char *p, heim_integer *data) } { - unsigned char *p = data->data; - while(*p == 0 && len > 0) { - p++; + unsigned char *q = data->data; + while(*q == 0 && len > 0) { + q++; len--; } data->length = len; - memmove(data->data, p, len); + memmove(data->data, q, len); } return 0; } @@ -103,3 +103,65 @@ der_print_hex_heim_integer (const heim_integer *data, char **p) } return 0; } + +int +der_print_heim_oid (const heim_oid *oid, char delim, char **str) +{ + struct rk_strpool *p = NULL; + int i; + + for (i = 0; i < oid->length ; i++) { + p = rk_strpoolprintf(p, "%d%s", + oid->components[i], + i < oid->length - 1 ? " " : ""); + if (p == NULL) { + *str = NULL; + return ENOMEM; + } + } + + *str = rk_strpoolcollect(p); + if (*str == NULL) + return ENOMEM; + return 0; +} + +int +der_parse_heim_oid (const char *str, const char *sep, heim_oid *data) +{ + char *s, *w, *brkt, *endptr; + unsigned int *c; + long l; + + data->length = 0; + data->components = NULL; + + if (sep == NULL) + sep = "."; + + s = strdup(str); + + for (w = strtok_r(s, sep, &brkt); + w != NULL; + w = strtok_r(NULL, sep, &brkt)) { + + c = realloc(data->components, + (data->length + 1) * sizeof(data->components[0])); + if (c == NULL) { + der_free_oid(data); + free(s); + return ENOMEM; + } + data->components = c; + + l = strtol(w, &endptr, 10); + if (*endptr != '\0' || l < 0 || l > INT_MAX) { + der_free_oid(data); + free(s); + return EINVAL; + } + data->components[data->length++] = l; + } + free(s); + return 0; +} diff --git a/source4/heimdal/lib/asn1/der_free.c b/source4/heimdal/lib/asn1/der_free.c index 8959c3b1c3..c3a6a17fff 100644 --- a/source4/heimdal/lib/asn1/der_free.c +++ b/source4/heimdal/lib/asn1/der_free.c @@ -33,37 +33,38 @@ #include "der_locl.h" -RCSID("$Id: der_free.c,v 1.11 2005/07/12 06:27:21 lha Exp $"); +RCSID("$Id: der_free.c,v 1.13 2006/10/14 05:30:47 lha Exp $"); void -free_general_string (heim_general_string *str) +der_free_general_string (heim_general_string *str) { free(*str); *str = NULL; } void -free_utf8string (heim_utf8_string *str) +der_free_utf8string (heim_utf8_string *str) { free(*str); *str = NULL; } void -free_printable_string (heim_printable_string *str) +der_free_printable_string (heim_printable_string *str) { free(*str); *str = NULL; } void -free_ia5_string (heim_ia5_string *str) +der_free_ia5_string (heim_ia5_string *str) { - free_general_string(str); + free(*str); + *str = NULL; } void -free_bmp_string (heim_bmp_string *k) +der_free_bmp_string (heim_bmp_string *k) { free(k->data); k->data = NULL; @@ -71,7 +72,7 @@ free_bmp_string (heim_bmp_string *k) } void -free_universal_string (heim_universal_string *k) +der_free_universal_string (heim_universal_string *k) { free(k->data); k->data = NULL; @@ -79,7 +80,7 @@ free_universal_string (heim_universal_string *k) } void -free_octet_string (heim_octet_string *k) +der_free_octet_string (heim_octet_string *k) { free(k->data); k->data = NULL; @@ -87,7 +88,7 @@ free_octet_string (heim_octet_string *k) } void -free_heim_integer (heim_integer *k) +der_free_heim_integer (heim_integer *k) { free(k->data); k->data = NULL; @@ -95,7 +96,7 @@ free_heim_integer (heim_integer *k) } void -free_oid (heim_oid *k) +der_free_oid (heim_oid *k) { free(k->components); k->components = NULL; @@ -103,7 +104,7 @@ free_oid (heim_oid *k) } void -free_bit_string (heim_bit_string *k) +der_free_bit_string (heim_bit_string *k) { free(k->data); k->data = NULL; diff --git a/source4/heimdal/lib/asn1/der_get.c b/source4/heimdal/lib/asn1/der_get.c index a75ab15c09..7808fa8165 100644 --- a/source4/heimdal/lib/asn1/der_get.c +++ b/source4/heimdal/lib/asn1/der_get.c @@ -33,7 +33,7 @@ #include "der_locl.h" -RCSID("$Id: der_get.c,v 1.45 2006/01/20 10:03:50 lha Exp $"); +RCSID("$Id: der_get.c,v 1.50 2006/10/19 16:27:44 lha Exp $"); #include <version.h> @@ -254,6 +254,8 @@ der_get_heim_integer (const unsigned char *p, size_t len, data->data = malloc(data->length); if (data->data == NULL) { data->length = 0; + if (size) + *size = 0; return ENOMEM; } q = &((unsigned char*)data->data)[data->length - 1]; @@ -276,6 +278,8 @@ der_get_heim_integer (const unsigned char *p, size_t len, data->data = malloc(data->length); if (data->data == NULL && data->length != 0) { data->length = 0; + if (size) + *size = 0; return ENOMEM; } memcpy(data->data, p, data->length); @@ -305,9 +309,10 @@ generalizedtime2time (const char *s, time_t *t) } tm.tm_year -= 1900; tm.tm_mon -= 1; - *t = timegm (&tm); + *t = _der_timegm (&tm); return 0; } +#undef timegm static int der_get_time (const unsigned char *p, size_t len, @@ -378,7 +383,7 @@ der_get_oid (const unsigned char *p, size_t len, u1 = u * 128 + (*p++ % 128); /* check that we don't overflow the element */ if (u1 < u) { - free_oid(data); + der_free_oid(data); return ASN1_OVERRUN; } u = u1; @@ -386,7 +391,7 @@ der_get_oid (const unsigned char *p, size_t len, data->components[n] = u; } if (n > 2 && p[-1] & 0x80) { - free_oid (data); + der_free_oid (data); return ASN1_OVERRUN; } data->length = n; diff --git a/source4/heimdal/lib/asn1/der_length.c b/source4/heimdal/lib/asn1/der_length.c index 2c017ad84e..9b2e9f0998 100644 --- a/source4/heimdal/lib/asn1/der_length.c +++ b/source4/heimdal/lib/asn1/der_length.c @@ -33,7 +33,7 @@ #include "der_locl.h" -RCSID("$Id: der_length.c,v 1.18 2006/01/20 10:04:46 lha Exp $"); +RCSID("$Id: der_length.c,v 1.19 2006/10/14 05:26:06 lha Exp $"); size_t _heim_len_unsigned (unsigned val) @@ -98,7 +98,7 @@ len_oid (const heim_oid *oid) } size_t -length_len (size_t len) +der_length_len (size_t len) { if (len < 128) return 1; @@ -113,67 +113,67 @@ length_len (size_t len) } size_t -length_integer (const int *data) +der_length_integer (const int *data) { return _heim_len_int (*data); } size_t -length_unsigned (const unsigned *data) +der_length_unsigned (const unsigned *data) { return _heim_len_unsigned(*data); } size_t -length_enumerated (const unsigned *data) +der_length_enumerated (const unsigned *data) { return _heim_len_int (*data); } size_t -length_general_string (const heim_general_string *data) +der_length_general_string (const heim_general_string *data) { return strlen(*data); } size_t -length_utf8string (const heim_utf8_string *data) +der_length_utf8string (const heim_utf8_string *data) { return strlen(*data); } size_t -length_printable_string (const heim_printable_string *data) +der_length_printable_string (const heim_printable_string *data) { return strlen(*data); } size_t -length_ia5_string (const heim_ia5_string *data) +der_length_ia5_string (const heim_ia5_string *data) { return strlen(*data); } size_t -length_bmp_string (const heim_bmp_string *data) +der_length_bmp_string (const heim_bmp_string *data) { return data->length * 2; } size_t -length_universal_string (const heim_universal_string *data) +der_length_universal_string (const heim_universal_string *data) { return data->length * 4; } size_t -length_octet_string (const heim_octet_string *k) +der_length_octet_string (const heim_octet_string *k) { return k->length; } size_t -length_heim_integer (const heim_integer *k) +der_length_heim_integer (const heim_integer *k) { if (k->length == 0) return 1; @@ -184,13 +184,13 @@ length_heim_integer (const heim_integer *k) } size_t -length_oid (const heim_oid *k) +der_length_oid (const heim_oid *k) { return len_oid (k); } size_t -length_generalized_time (const time_t *t) +der_length_generalized_time (const time_t *t) { heim_octet_string k; size_t ret; @@ -202,7 +202,7 @@ length_generalized_time (const time_t *t) } size_t -length_utctime (const time_t *t) +der_length_utctime (const time_t *t) { heim_octet_string k; size_t ret; @@ -214,13 +214,13 @@ length_utctime (const time_t *t) } size_t -length_boolean (const int *k) +der_length_boolean (const int *k) { return 1; } size_t -length_bit_string (const heim_bit_string *k) +der_length_bit_string (const heim_bit_string *k) { return (k->length + 7) / 8 + 1; } diff --git a/source4/heimdal/lib/asn1/der_locl.h b/source4/heimdal/lib/asn1/der_locl.h index 1127383e6c..1a87aaaee9 100644 --- a/source4/heimdal/lib/asn1/der_locl.h +++ b/source4/heimdal/lib/asn1/der_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: der_locl.h,v 1.6 2005/07/12 06:27:22 lha Exp $ */ +/* $Id: der_locl.h,v 1.8 2006/10/19 16:24:02 lha Exp $ */ #ifndef __DER_LOCL_H__ #define __DER_LOCL_H__ @@ -53,10 +53,7 @@ #include <asn1_err.h> #include <der.h> -#ifndef HAVE_TIMEGM -time_t timegm (struct tm *); -#endif - +time_t _der_timegm (struct tm *); size_t _heim_len_unsigned (unsigned); size_t _heim_len_int (int); diff --git a/source4/heimdal/lib/asn1/der_put.c b/source4/heimdal/lib/asn1/der_put.c index b006f233ca..2fe90df9a9 100644 --- a/source4/heimdal/lib/asn1/der_put.c +++ b/source4/heimdal/lib/asn1/der_put.c @@ -335,6 +335,9 @@ der_put_utctime (unsigned char *p, size_t len, return 0; } +/* This API is not what you might expect. p is a pointer to the *end* + * (last byte) of the buffer, of length len */ + int der_put_oid (unsigned char *p, size_t len, const heim_oid *data, size_t *size) diff --git a/source4/heimdal/lib/asn1/digest.asn1 b/source4/heimdal/lib/asn1/digest.asn1 new file mode 100644 index 0000000000..1f8f18b5cd --- /dev/null +++ b/source4/heimdal/lib/asn1/digest.asn1 @@ -0,0 +1,115 @@ +-- $Id: digest.asn1,v 1.9 2006/08/25 11:57:54 lha Exp $ + +DIGEST DEFINITIONS ::= +BEGIN + +IMPORTS EncryptedData, Principal FROM krb5; + +DigestInit ::= SEQUENCE { + type UTF8String, -- http, sasl, chap, cram-md5 -- + channel [0] SEQUENCE { + cb-type UTF8String, + cb-binding UTF8String + } OPTIONAL, + hostname [1] UTF8String OPTIONAL -- for chap/cram-md5 +} + +DigestInitReply ::= SEQUENCE { + nonce UTF8String, -- service nonce/challange + opaque UTF8String, -- server state + identifier [0] UTF8String OPTIONAL +} + + +DigestRequest ::= SEQUENCE { + type UTF8String, -- http, sasl-md5, chap, cram-md5 -- + digest UTF8String, -- http:md5/md5-sess sasl:clear/int/conf -- + username UTF8String, -- username user used + authid [0] UTF8String OPTIONAL, + authentication-user [1] Principal OPTIONAL, -- principal to get key from + realm [2] UTF8String OPTIONAL, + method [3] UTF8String OPTIONAL, + uri [4] UTF8String OPTIONAL, + serverNonce UTF8String, -- same as "DigestInitReply.nonce" + clientNonce [5] UTF8String OPTIONAL, + nonceCount [6] UTF8String OPTIONAL, + qop [7] UTF8String OPTIONAL, + identifier [8] UTF8String OPTIONAL, + hostname [9] UTF8String OPTIONAL, + opaque UTF8String -- same as "DigestInitReply.opaque" +} +-- opaque = hex(cksum(type|serverNonce|identifier|hostname,digest-key)) +-- serverNonce = hex(time[4bytes]random[12bytes])(-cbType:cbBinding) + + +DigestError ::= SEQUENCE { + reason UTF8String, + code INTEGER (-2147483648..2147483647) +} + +DigestResponse ::= SEQUENCE { + responseData UTF8String, + rsp [0] UTF8String OPTIONAL, + tickets [1] SEQUENCE OF OCTET STRING OPTIONAL, + channel [2] SEQUENCE { + cb-type UTF8String, + cb-binding UTF8String + } OPTIONAL, + hash-a1 [3] OCTET STRING OPTIONAL +} + +DigestReqInner ::= CHOICE { + init [0] DigestInit, + digestRequest [1] DigestRequest +} + +DigestREQ ::= [APPLICATION 128] SEQUENCE { + apReq [0] OCTET STRING, + innerReq [1] EncryptedData +} + +DigestRepInner ::= CHOICE { + error [0] DigestError, + initReply [1] DigestInitReply, + response [2] DigestResponse +} + +DigestREP ::= [APPLICATION 129] SEQUENCE { + apRep [0] OCTET STRING, + innerRep [1] EncryptedData +} + + +-- HTTP + +-- md5 +-- A1 = unq(username-value) ":" unq(realm-value) ":" passwd +-- md5-sess +-- A1 = HEX(H(unq(username-value) ":" unq(realm-value) ":" passwd ) ":" unq(nonce-value) ":" unq(cnonce-value)) + +-- qop == auth +-- A2 = Method ":" digest-uri-value +-- qop == auth-int +-- A2 = Method ":" digest-uri-value ":" H(entity-body) + +-- request-digest = HEX(KD(HEX(H(A1)), +-- unq(nonce-value) ":" nc-value ":" unq(cnonce-value) ":" unq(qop-value) ":" HEX(H(A2)))) +-- no "qop" +-- request-digest = HEX(KD(HEX(H(A1)), unq(nonce-value) ":" HEX(H(A2)))) + + +-- SASL: +-- SS = H( { unq(username-value), ":", unq(realm-value), ":", password } ) +-- A1 = { SS, ":", unq(nonce-value), ":", unq(cnonce-value) } +-- A1 = { SS, ":", unq(nonce-value), ":", unq(cnonce-value), ":", unq(authzid-value) } + +-- A2 = "AUTHENTICATE:", ":", digest-uri-value +-- qop == auth-int,auth-conf +-- A2 = "AUTHENTICATE:", ":", digest-uri-value, ":00000000000000000000000000000000" + +-- response-value = HEX( KD ( HEX(H(A1)), +-- { unq(nonce-value), ":" nc-value, ":", +-- unq(cnonce-value), ":", qop-value, ":", +-- HEX(H(A2)) })) + +END diff --git a/source4/heimdal/lib/asn1/gen.c b/source4/heimdal/lib/asn1/gen.c index 3d7c3983ac..c3af316c88 100644 --- a/source4/heimdal/lib/asn1/gen.c +++ b/source4/heimdal/lib/asn1/gen.c @@ -33,7 +33,7 @@ #include "gen_locl.h" -RCSID("$Id: gen.c,v 1.67 2006/03/31 02:52:21 lha Exp $"); +RCSID("$Id: gen.c,v 1.69 2006/10/14 05:11:52 lha Exp $"); FILE *headerfile, *codefile, *logfile; @@ -145,6 +145,9 @@ init_generate (const char *filename, const char *base) " size_t length;\n" " void *data;\n" "} heim_bit_string;\n\n"); + fprintf (headerfile, + "typedef struct heim_octet_string heim_any;\n" + "typedef struct heim_octet_string heim_any_set;\n\n"); fputs("#define ASN1_MALLOC_ENCODE(T, B, BL, S, L, R) \\\n" " do { \\\n" " (BL) = length_##T((S)); \\\n" @@ -774,6 +777,7 @@ generate_type (const Symbol *s) generate_type_free (s); generate_type_length (s); generate_type_copy (s); + generate_type_seq (s); generate_glue (s->type, s->gen_name); fprintf(headerfile, "\n\n"); close_codefile(); diff --git a/source4/heimdal/lib/asn1/gen_copy.c b/source4/heimdal/lib/asn1/gen_copy.c index 07b7efba2c..9455f33c6f 100644 --- a/source4/heimdal/lib/asn1/gen_copy.c +++ b/source4/heimdal/lib/asn1/gen_copy.c @@ -33,14 +33,14 @@ #include "gen_locl.h" -RCSID("$Id: gen_copy.c,v 1.16 2005/07/12 06:27:26 lha Exp $"); +RCSID("$Id: gen_copy.c,v 1.18 2006/10/14 05:34:19 lha Exp $"); static int used_fail; static void copy_primitive (const char *typename, const char *from, const char *to) { - fprintf (codefile, "if(copy_%s(%s, %s)) goto fail;\n", + fprintf (codefile, "if(der_copy_%s(%s, %s)) goto fail;\n", typename, from, to); used_fail++; } @@ -86,7 +86,7 @@ copy_type (const char *from, const char *to, const Type *t, int preserve) if ((t->type == TSequence || t->type == TChoice) && preserve) { fprintf(codefile, "{ int ret;\n" - "ret = copy_octet_string(&(%s)->_save, &(%s)->_save);\n" + "ret = der_copy_octet_string(&(%s)->_save, &(%s)->_save);\n" "if (ret) goto fail;\n" "}\n", from, to); @@ -140,7 +140,7 @@ copy_type (const char *from, const char *to, const Type *t, int preserve) if (have_ellipsis) { fprintf(codefile, "case %s: {\n" "int ret;\n" - "ret = copy_octet_string(&(%s)->u.%s, &(%s)->u.%s);\n" + "ret=der_copy_octet_string(&(%s)->u.%s, &(%s)->u.%s);\n" "if (ret) goto fail;\n" "break;\n" "}\n", diff --git a/source4/heimdal/lib/asn1/gen_decode.c b/source4/heimdal/lib/asn1/gen_decode.c index 6461a0ada9..193dab40e1 100644 --- a/source4/heimdal/lib/asn1/gen_decode.c +++ b/source4/heimdal/lib/asn1/gen_decode.c @@ -34,7 +34,7 @@ #include "gen_locl.h" #include "lex.h" -RCSID("$Id: gen_decode.c,v 1.29 2005/09/21 00:30:37 lha Exp $"); +RCSID("$Id: gen_decode.c,v 1.30 2006/09/24 09:13:12 lha Exp $"); static void decode_primitive (const char *typename, const char *name, const char *forwstr) @@ -307,7 +307,7 @@ decode_type (const char *name, const Type *t, int optional, decode_type (s, m->type, m->optional, forwstr, m->gen_name); free (s); } - + break; } case TSet: { @@ -632,7 +632,7 @@ generate_type_decode (const Symbol *s) case TType: case TChoice: fprintf (codefile, - "size_t ret = 0, reallen;\n" + "size_t ret = 0;\n" "size_t l;\n" "int e;\n"); if (preserve) @@ -640,7 +640,6 @@ generate_type_decode (const Symbol *s) fprintf (codefile, "\n"); fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */ - fprintf (codefile, "reallen = 0;\n"); decode_type ("data", s->type, 0, "goto fail", "Top"); if (preserve) diff --git a/source4/heimdal/lib/asn1/gen_free.c b/source4/heimdal/lib/asn1/gen_free.c index 36c7474a03..2b143bf818 100644 --- a/source4/heimdal/lib/asn1/gen_free.c +++ b/source4/heimdal/lib/asn1/gen_free.c @@ -33,12 +33,12 @@ #include "gen_locl.h" -RCSID("$Id: gen_free.c,v 1.14 2005/07/25 21:28:29 lha Exp $"); +RCSID("$Id: gen_free.c,v 1.16 2006/10/14 05:33:58 lha Exp $"); static void free_primitive (const char *typename, const char *name) { - fprintf (codefile, "free_%s(%s);\n", typename, name); + fprintf (codefile, "der_free_%s(%s);\n", typename, name); } static void @@ -78,7 +78,7 @@ free_type (const char *name, const Type *t, int preserve) break; if ((t->type == TSequence || t->type == TChoice) && preserve) - fprintf(codefile, "free_octet_string(&data->_save);\n"); + fprintf(codefile, "der_free_octet_string(&data->_save);\n"); if(t->type == TChoice) fprintf(codefile, "switch((%s)->element) {\n", name); @@ -115,7 +115,7 @@ free_type (const char *name, const Type *t, int preserve) if (have_ellipsis) fprintf(codefile, "case %s:\n" - "free_octet_string(&(%s)->u.%s);\n" + "der_free_octet_string(&(%s)->u.%s);\n" "break;", have_ellipsis->label, name, have_ellipsis->gen_name); diff --git a/source4/heimdal/lib/asn1/gen_length.c b/source4/heimdal/lib/asn1/gen_length.c index f3869fa5f2..0c92225b92 100644 --- a/source4/heimdal/lib/asn1/gen_length.c +++ b/source4/heimdal/lib/asn1/gen_length.c @@ -33,14 +33,14 @@ #include "gen_locl.h" -RCSID("$Id: gen_length.c,v 1.19 2005/08/23 11:51:41 lha Exp $"); +RCSID("$Id: gen_length.c,v 1.21 2006/10/14 05:28:28 lha Exp $"); static void length_primitive (const char *typename, const char *name, const char *variable) { - fprintf (codefile, "%s += length_%s(%s);\n", variable, typename, name); + fprintf (codefile, "%s += der_length_%s(%s);\n", variable, typename, name); } static size_t @@ -247,7 +247,7 @@ length_type (const char *name, const Type *t, if (tname == NULL) errx(1, "malloc"); length_type (name, t->subtype, variable, tname); - fprintf (codefile, "ret += %lu + length_len (ret);\n", + fprintf (codefile, "ret += %lu + der_length_len (ret);\n", (unsigned long)length_tag(t->tag.tagvalue)); free(tname); break; diff --git a/source4/heimdal/lib/asn1/gen_locl.h b/source4/heimdal/lib/asn1/gen_locl.h index 5a2ba85c7a..c9ea714c5f 100644 --- a/source4/heimdal/lib/asn1/gen_locl.h +++ b/source4/heimdal/lib/asn1/gen_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: gen_locl.h,v 1.13 2005/08/23 10:48:15 lha Exp $ */ +/* $Id: gen_locl.h,v 1.14 2006/09/05 12:29:18 lha Exp $ */ #ifndef __GEN_LOCL_H__ #define __GEN_LOCL_H__ @@ -58,11 +58,10 @@ void generate_type (const Symbol *); void generate_constant (const Symbol *); void generate_type_encode (const Symbol *); void generate_type_decode (const Symbol *); -void generate_seq_type_decode (const Symbol *); void generate_type_free (const Symbol *); void generate_type_length (const Symbol *); void generate_type_copy (const Symbol *); -void generate_type_maybe (const Symbol *); +void generate_type_seq (const Symbol *); void generate_glue (const Type *, const char*); const char *classname(Der_class); @@ -79,6 +78,7 @@ void add_import(const char *); int yyparse(void); int preserve_type(const char *); +int seq_type(const char *); extern FILE *headerfile, *codefile, *logfile; extern int dce_fix; diff --git a/source4/heimdal/lib/asn1/gen_seq.c b/source4/heimdal/lib/asn1/gen_seq.c new file mode 100644 index 0000000000..fa3813fd61 --- /dev/null +++ b/source4/heimdal/lib/asn1/gen_seq.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "gen_locl.h" + +RCSID("$Id: gen_seq.c,v 1.4 2006/10/04 10:18:10 lha Exp $"); + +void +generate_type_seq (const Symbol *s) +{ + char *subname; + Type *type; + + if (!seq_type(s->name)) + return; + type = s->type; + while(type->type == TTag) + type = type->subtype; + + if (type->type != TSequenceOf) { + printf("%s not seq of %d\n", s->name, (int)type->type); + return; + } + + /* + * Require the subtype to be a type so we can name it and use + * copy_/free_ + */ + + if (type->subtype->type != TType) { + fprintf(stderr, "%s subtype is not a type, can't generate " + "sequence code for this case: %d\n", + s->name, (int)type->subtype->type); + exit(1); + } + + subname = type->subtype->symbol->gen_name; + + fprintf (headerfile, + "int add_%s (%s *, const %s *);\n" + "int remove_%s (%s *, unsigned int);\n", + s->gen_name, s->gen_name, subname, + s->gen_name, s->gen_name); + + fprintf (codefile, "int\n" + "add_%s(%s *data, const %s *element)\n" + "{\n", + s->gen_name, s->gen_name, subname); + + fprintf (codefile, + "int ret;\n" + "void *ptr;\n" + "\n" + "ptr = realloc(data->val, \n" + "\t(data->len + 1) * sizeof(data->val[0]));\n" + "if (ptr == NULL) return ENOMEM;\n" + "data->val = ptr;\n\n" + "ret = copy_%s(element, &data->val[data->len]);\n" + "if (ret) return ret;\n" + "data->len++;\n" + "return 0;\n", + subname); + + fprintf (codefile, "}\n\n"); + + fprintf (codefile, "int\n" + "remove_%s(%s *data, unsigned int element)\n" + "{\n", + s->gen_name, s->gen_name); + + fprintf (codefile, + "void *ptr;\n" + "\n" + "if (data->len == 0 || element >= data->len)\n" + "\treturn ASN1_OVERRUN;\n" + "free_%s(&data->val[element]);\n" + "data->len--;\n" + /* don't move if its the last element */ + "if (element < data->len)\n" + "\tmemmove(&data->val[element], &data->val[element + 1], \n" + "\t\tsizeof(data->val[0]) * data->len);\n" + /* resize but don't care about failures since it doesn't matter */ + "ptr = realloc(data->val, data->len * sizeof(data->val[0]));\n" + "if (ptr) data->val = ptr;\n" + "return 0;\n", + subname); + + fprintf (codefile, "}\n\n"); +} diff --git a/source4/heimdal/lib/asn1/heim_asn1.h b/source4/heimdal/lib/asn1/heim_asn1.h index 99f8e9514a..afee6f4218 100644 --- a/source4/heimdal/lib/asn1/heim_asn1.h +++ b/source4/heimdal/lib/asn1/heim_asn1.h @@ -34,9 +34,6 @@ #ifndef __HEIM_ANY_H__ #define __HEIM_ANY_H__ 1 -typedef struct heim_octet_string heim_any; -typedef struct heim_octet_string heim_any_set; - int encode_heim_any(unsigned char *, size_t, const heim_any *, size_t *); int decode_heim_any(const unsigned char *, size_t, heim_any *, size_t *); void free_heim_any(heim_any *); diff --git a/source4/heimdal/lib/asn1/k5.asn1 b/source4/heimdal/lib/asn1/k5.asn1 index e314adee0e..3f501f0592 100644 --- a/source4/heimdal/lib/asn1/k5.asn1 +++ b/source4/heimdal/lib/asn1/k5.asn1 @@ -1,4 +1,4 @@ --- $Id: k5.asn1,v 1.47 2006/03/27 22:52:11 lha Exp $ +-- $Id: k5.asn1,v 1.50 2006/09/11 13:28:59 lha Exp $ KERBEROS5 DEFINITIONS ::= BEGIN @@ -70,10 +70,11 @@ PADATA-TYPE ::= INTEGER { KRB5-PADATA-TD-REQ-NONCE(107), -- INTEGER KRB5-PADATA-TD-REQ-SEQ(108), -- INTEGER KRB5-PADATA-PA-PAC-REQUEST(128), -- jbrezak@exchange.microsoft.com - KRB5-PADATA-PK-AS-09-BINDING(132) -- client send this to + KRB5-PADATA-PK-AS-09-BINDING(132), -- client send this to -- tell KDC that is supports -- the asCheckSum in the -- PK-AS-REP + KRB5-PADATA-S4U2SELF(-17) } AUTHDATA-TYPE ::= INTEGER { @@ -89,7 +90,8 @@ AUTHDATA-TYPE ::= INTEGER { KRB5-AUTHDATA-SESAME(65), KRB5-AUTHDATA-OSF-DCE-PKI-CERTID(66), KRB5-AUTHDATA-WIN2K-PAC(128), - KRB5-AUTHDATA-GSS-API-ETYPE-NEGOTIATION(129) -- Authenticator only + KRB5-AUTHDATA-GSS-API-ETYPE-NEGOTIATION(129), -- Authenticator only + KRB5-AUTHDATA-SIGNTICKET(-17) } -- checksumtypes @@ -138,12 +140,7 @@ ENCTYPE ::= INTEGER { ETYPE_DES_CFB64_NONE(-0x1002), ETYPE_DES_PCBC_NONE(-0x1003), ETYPE_DIGEST_MD5_NONE(-0x1004), -- private use, lukeh@padl.com - ETYPE_CRAM_MD5_NONE(-0x1005), -- private use, lukeh@padl.com - ETYPE_RC2_CBC_NONE(-0x1006), - ETYPE_AES128_CBC_NONE(-0x1007), - ETYPE_AES192_CBC_NONE(-0x1008), - ETYPE_AES256_CBC_NONE(-0x1009), - ETYPE_DES3_CBC_NONE_CMS(-0x100a) + ETYPE_CRAM_MD5_NONE(-0x1005) -- private use, lukeh@padl.com } @@ -186,11 +183,13 @@ HostAddresses ::= SEQUENCE OF HostAddress KerberosTime ::= GeneralizedTime -- Specifying UTC time zone (Z) -AuthorizationData ::= SEQUENCE OF SEQUENCE { +AuthorizationDataElement ::= SEQUENCE { ad-type[0] krb5int32, ad-data[1] OCTET STRING } +AuthorizationData ::= SEQUENCE OF AuthorizationDataElement + APOptions ::= BIT STRING { reserved(0), use-session-key(1), @@ -307,7 +306,7 @@ Authenticator ::= [APPLICATION 2] SEQUENCE { subkey[6] EncryptionKey OPTIONAL, seq-number[7] krb5uint32 OPTIONAL, authorization-data[8] AuthorizationData OPTIONAL - } +} PA-DATA ::= SEQUENCE { -- might be encoded AP-REQ @@ -601,16 +600,29 @@ PA-ENC-SAM-RESPONSE-ENC ::= SEQUENCE { ... } --- This is really part of CMS, but its here because KCRYPTO provides --- the crypto framework for CMS glue in heimdal. - -RC2CBCParameter ::= SEQUENCE { - rc2ParameterVersion krb5int32, - iv OCTET STRING -- exactly 8 octets +PA-S4U2Self ::= SEQUENCE { + name[0] PrincipalName, + realm[1] Realm, + cksum[2] Checksum, + auth[3] GeneralString } -CBCParameter ::= OCTET STRING +KRB5SignedPathPrincipals ::= SEQUENCE OF Principal +-- never encoded on the wire, just used to checksum over +KRB5SignedPathData ::= SEQUENCE { + encticket[0] EncTicketPart, + delegated[1] KRB5SignedPathPrincipals OPTIONAL +} + +KRB5SignedPath ::= SEQUENCE { + -- DERcoded KRB5SignedPathData + -- krbtgt key (etype), KeyUsage = XXX + etype[0] ENCTYPE, + cksum[1] Checksum, + -- srvs delegated though + delegated[2] KRB5SignedPathPrincipals OPTIONAL +} END diff --git a/source4/heimdal/lib/asn1/lex.c b/source4/heimdal/lib/asn1/lex.c index 70e893197d..10b4d65a7e 100644 --- a/source4/heimdal/lib/asn1/lex.c +++ b/source4/heimdal/lib/asn1/lex.c @@ -1,94 +1,32 @@ -#include "config.h" +/* A lexical scanner generated by flex*/ -#line 3 "lex.yy.c" - -#define YY_INT_ALIGNED short int - -/* A lexical scanner generated by flex */ +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ + */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 33 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ -/* begin standard C headers. */ #include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -/* end standard C headers. */ - -/* flex integer type definitions */ - -#ifndef FLEXINT_H -#define FLEXINT_H - -/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ - -#if __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif +#include <unistd.h> -#include <inttypes.h> -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; -#endif /* ! C99 */ -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus #endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) #endif -#endif /* ! FLEXINT_H */ #ifdef __cplusplus +#include <stdlib.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST @@ -96,17 +34,34 @@ typedef unsigned int flex_uint32_t; #if __STDC__ +#define YY_USE_PROTOS #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + /* Returned upon end-of-file. */ #define YY_NULL 0 @@ -121,75 +76,80 @@ typedef unsigned int flex_uint32_t; * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ -#define BEGIN (yy_start) = 1 + 2 * +#define BEGIN yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ -#define YY_START (((yy_start) - 1) / 2) +#define YY_START ((yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart(yyin ) +#define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ -#ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 -#endif -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) - -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif extern int yyleng; - extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 - #define YY_LESS_LINENO(n) - -/* Return all but the first "n" matched characters back to the input stream. */ +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = (yy_hold_char); \ + *yy_cp = yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ - (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) -#define unput(c) yyunput( c, (yytext_ptr) ) +#define unput(c) yyunput( c, yytext_ptr ) + +/* Some routines like yy_flex_realloc() are emitted as static but are + not called by all lexers. This generates warnings in some compilers, + notably GCC. Arrange to suppress these. */ +#ifdef __GNUC__ +#define YY_MAY_BE_UNUSED __attribute__((unused)) +#else +#define YY_MAY_BE_UNUSED +#endif /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T typedef unsigned int yy_size_t; -#endif -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE + struct yy_buffer_state { FILE *yy_input_file; @@ -226,16 +186,12 @@ struct yy_buffer_state */ int yy_at_bol; - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; - #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process @@ -249,38 +205,28 @@ struct yy_buffer_state * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ -/* Stack of input buffers. */ -static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ -static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ -static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ +static YY_BUFFER_STATE yy_current_buffer = 0; /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". - * - * Returns the top of the stack, or NULL. */ -#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ - ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ - : NULL) +#define YY_CURRENT_BUFFER yy_current_buffer -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; + static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; -static int yy_init = 0; /* whether we need to initialize */ +static int yy_init = 1; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches @@ -288,92 +234,66 @@ static int yy_start = 0; /* start state number */ */ static int yy_did_buffer_switch_on_eof; -void yyrestart (FILE *input_file ); -void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); -void yy_delete_buffer (YY_BUFFER_STATE b ); -void yy_flush_buffer (YY_BUFFER_STATE b ); -void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); -void yypop_buffer_state (void ); +void yyrestart YY_PROTO(( FILE *input_file )); -static void yyensure_buffer_stack (void ); -static void yy_load_buffer_state (void ); -static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) -#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); -YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); -YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); - -void *yyalloc (yy_size_t ); -void *yyrealloc (void *,yy_size_t ); -void yyfree (void * ); +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )) YY_MAY_BE_UNUSED; +static void yy_flex_free YY_PROTO(( void * )); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ - if ( ! YY_CURRENT_BUFFER ){ \ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer(yyin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ - if ( ! YY_CURRENT_BUFFER ){\ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer(yyin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ } -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) typedef unsigned char YY_CHAR; - FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; - typedef int yy_state_type; - -extern int yylineno; - -int yylineno = 1; - extern char *yytext; #define yytext_ptr yytext -static yy_state_type yy_get_previous_state (void ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); -static int yy_get_next_buffer (void ); -static void yy_fatal_error (yyconst char msg[] ); +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ - (yytext_ptr) = yy_bp; \ - yyleng = (size_t) (yy_cp - yy_bp); \ - (yy_hold_char) = *yy_cp; \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; + yy_c_buf_p = yy_cp; #define YY_NUM_RULES 95 #define YY_END_OF_BUFFER 96 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static yyconst flex_int16_t yy_accept[568] = +static yyconst short int yy_accept[568] = { 0, 0, 0, 96, 94, 90, 91, 87, 81, 81, 94, 94, 88, 88, 94, 89, 89, 89, 89, 89, 89, @@ -439,7 +359,7 @@ static yyconst flex_int16_t yy_accept[568] = 32, 89, 59, 70, 77, 53, 0 } ; -static yyconst flex_int32_t yy_ec[256] = +static yyconst int yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -471,7 +391,7 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[70] = +static yyconst int yy_meta[70] = { 0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 1, 1, 3, 3, @@ -482,7 +402,7 @@ static yyconst flex_int32_t yy_meta[70] = 2, 2, 2, 2, 2, 2, 2, 2, 2 } ; -static yyconst flex_int16_t yy_base[570] = +static yyconst short int yy_base[570] = { 0, 0, 0, 636, 637, 637, 637, 637, 637, 63, 627, 628, 70, 77, 616, 74, 72, 76, 609, 65, 81, @@ -548,7 +468,7 @@ static yyconst flex_int16_t yy_base[570] = 0, 101, 0, 0, 0, 0, 637, 223, 69 } ; -static yyconst flex_int16_t yy_def[570] = +static yyconst short int yy_def[570] = { 0, 567, 1, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 567, 568, 568, 568, 568, 568, 568, @@ -614,7 +534,7 @@ static yyconst flex_int16_t yy_def[570] = 568, 568, 568, 568, 568, 568, 0, 567, 567 } ; -static yyconst flex_int16_t yy_nxt[707] = +static yyconst short int yy_nxt[707] = { 0, 4, 5, 6, 7, 8, 4, 9, 10, 11, 12, 13, 13, 13, 13, 13, 13, 14, 4, 15, 16, @@ -696,7 +616,7 @@ static yyconst flex_int16_t yy_nxt[707] = 567, 567, 567, 567, 567, 567 } ; -static yyconst flex_int16_t yy_chk[707] = +static yyconst short int yy_chk[707] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -781,9 +701,6 @@ static yyconst flex_int16_t yy_chk[707] = static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; -extern int yy_flex_debug; -int yy_flex_debug = 0; - /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ @@ -793,6 +710,7 @@ int yy_flex_debug = 0; #define YY_RESTORE_YY_MORE_OFFSET char *yytext; #line 1 "lex.l" +#define INITIAL 0 #line 2 "lex.l" /* * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan @@ -827,7 +745,7 @@ char *yytext; * SUCH DAMAGE. */ -/* $Id: lex.l,v 1.27 2005/09/13 18:17:16 lha Exp $ */ +/* $Id: lex.l,v 1.31 2006/10/21 11:57:22 lha Exp $ */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -851,23 +769,8 @@ static unsigned lineno = 1; static void unterminated(const char *, unsigned); -#line 854 "lex.yy.c" - -#define INITIAL 0 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include <unistd.h> -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -static int yy_init_globals (void ); +/* This is for broken old lexes (solaris 10 and hpux) */ +#line 774 "lex.c" /* Macros after this point can all be overridden by user definitions in * section 1. @@ -875,30 +778,65 @@ static int yy_init_globals (void ); #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus -extern "C" int yywrap (void ); +extern "C" int yywrap YY_PROTO(( void )); #else -extern int yywrap (void ); +extern int yywrap YY_PROTO(( void )); +#endif #endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); #endif - static void yyunput (int c,char *buf_ptr ); - #ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ); +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ); +static int yy_flex_strlen YY_PROTO(( yyconst char * )); #endif #ifndef YY_NO_INPUT - #ifdef __cplusplus -static int yyinput (void ); +static int yyinput YY_PROTO(( void )); #else -static int input (void ); +static int input YY_PROTO(( void )); +#endif #endif +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif #endif /* Amount of stuff to slurp up with each read. */ @@ -907,6 +845,7 @@ static int input (void ); #endif /* Copy whatever the last rule matched to the standard output. */ + #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). @@ -919,10 +858,9 @@ static int input (void ); */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + if ( yy_current_buffer->yy_is_interactive ) \ { \ - int c = '*'; \ - size_t n; \ + int c = '*', n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -932,22 +870,9 @@ static int input (void ); YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ - else \ - { \ - errno=0; \ - while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(yyin); \ - } \ - }\ -\ - + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - @@ -968,18 +893,12 @@ static int input (void ); #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif -/* end tables serialization structures and prototypes */ - /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int yylex (void); - -#define YY_DECL int yylex (void) -#endif /* !YY_DECL */ +#define YY_DECL int yylex YY_PROTO(( void )) +#endif /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. @@ -996,28 +915,26 @@ extern int yylex (void); #define YY_RULE_SETUP \ YY_USER_ACTION -/** The main scanner function which does all the work. - */ YY_DECL -{ + { register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; + register char *yy_cp = NULL, *yy_bp = NULL; register int yy_act; - -#line 62 "lex.l" -#line 1009 "lex.yy.c" +#line 68 "lex.l" - if ( !(yy_init) ) +#line 927 "lex.c" + + if ( yy_init ) { - (yy_init) = 1; + yy_init = 0; #ifdef YY_USER_INIT YY_USER_INIT; #endif - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ + if ( ! yy_start ) + yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; @@ -1025,36 +942,34 @@ YY_DECL if ( ! yyout ) yyout = stdout; - if ( ! YY_CURRENT_BUFFER ) { - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer(yyin,YY_BUF_SIZE ); - } + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); - yy_load_buffer_state( ); + yy_load_buffer_state(); } while ( 1 ) /* loops until end-of-file is reached */ { - yy_cp = (yy_c_buf_p); + yy_cp = yy_c_buf_p; /* Support of yytext. */ - *yy_cp = (yy_hold_char); + *yy_cp = yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; - yy_current_state = (yy_start); + yy_current_state = yy_start; yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { @@ -1071,447 +986,449 @@ yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; + do_action: /* This label is used only to access EOF actions. */ + switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = (yy_hold_char); - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; goto yy_find_action; case 1: YY_RULE_SETUP -#line 63 "lex.l" +#line 69 "lex.l" { return kw_ABSENT; } YY_BREAK case 2: YY_RULE_SETUP -#line 64 "lex.l" +#line 70 "lex.l" { return kw_ABSTRACT_SYNTAX; } YY_BREAK case 3: YY_RULE_SETUP -#line 65 "lex.l" +#line 71 "lex.l" { return kw_ALL; } YY_BREAK case 4: YY_RULE_SETUP -#line 66 "lex.l" +#line 72 "lex.l" { return kw_APPLICATION; } YY_BREAK case 5: YY_RULE_SETUP -#line 67 "lex.l" +#line 73 "lex.l" { return kw_AUTOMATIC; } YY_BREAK case 6: YY_RULE_SETUP -#line 68 "lex.l" +#line 74 "lex.l" { return kw_BEGIN; } YY_BREAK case 7: YY_RULE_SETUP -#line 69 "lex.l" +#line 75 "lex.l" { return kw_BIT; } YY_BREAK case 8: YY_RULE_SETUP -#line 70 "lex.l" +#line 76 "lex.l" { return kw_BMPString; } YY_BREAK case 9: YY_RULE_SETUP -#line 71 "lex.l" +#line 77 "lex.l" { return kw_BOOLEAN; } YY_BREAK case 10: YY_RULE_SETUP -#line 72 "lex.l" +#line 78 "lex.l" { return kw_BY; } YY_BREAK case 11: YY_RULE_SETUP -#line 73 "lex.l" +#line 79 "lex.l" { return kw_CHARACTER; } YY_BREAK case 12: YY_RULE_SETUP -#line 74 "lex.l" +#line 80 "lex.l" { return kw_CHOICE; } YY_BREAK case 13: YY_RULE_SETUP -#line 75 "lex.l" +#line 81 "lex.l" { return kw_CLASS; } YY_BREAK case 14: YY_RULE_SETUP -#line 76 "lex.l" +#line 82 "lex.l" { return kw_COMPONENT; } YY_BREAK case 15: YY_RULE_SETUP -#line 77 "lex.l" +#line 83 "lex.l" { return kw_COMPONENTS; } YY_BREAK case 16: YY_RULE_SETUP -#line 78 "lex.l" +#line 84 "lex.l" { return kw_CONSTRAINED; } YY_BREAK case 17: YY_RULE_SETUP -#line 79 "lex.l" +#line 85 "lex.l" { return kw_CONTAINING; } YY_BREAK case 18: YY_RULE_SETUP -#line 80 "lex.l" +#line 86 "lex.l" { return kw_DEFAULT; } YY_BREAK case 19: YY_RULE_SETUP -#line 81 "lex.l" +#line 87 "lex.l" { return kw_DEFINITIONS; } YY_BREAK case 20: YY_RULE_SETUP -#line 82 "lex.l" +#line 88 "lex.l" { return kw_EMBEDDED; } YY_BREAK case 21: YY_RULE_SETUP -#line 83 "lex.l" +#line 89 "lex.l" { return kw_ENCODED; } YY_BREAK case 22: YY_RULE_SETUP -#line 84 "lex.l" +#line 90 "lex.l" { return kw_END; } YY_BREAK case 23: YY_RULE_SETUP -#line 85 "lex.l" +#line 91 "lex.l" { return kw_ENUMERATED; } YY_BREAK case 24: YY_RULE_SETUP -#line 86 "lex.l" +#line 92 "lex.l" { return kw_EXCEPT; } YY_BREAK case 25: YY_RULE_SETUP -#line 87 "lex.l" +#line 93 "lex.l" { return kw_EXPLICIT; } YY_BREAK case 26: YY_RULE_SETUP -#line 88 "lex.l" +#line 94 "lex.l" { return kw_EXPORTS; } YY_BREAK case 27: YY_RULE_SETUP -#line 89 "lex.l" +#line 95 "lex.l" { return kw_EXTENSIBILITY; } YY_BREAK case 28: YY_RULE_SETUP -#line 90 "lex.l" +#line 96 "lex.l" { return kw_EXTERNAL; } YY_BREAK case 29: YY_RULE_SETUP -#line 91 "lex.l" +#line 97 "lex.l" { return kw_FALSE; } YY_BREAK case 30: YY_RULE_SETUP -#line 92 "lex.l" +#line 98 "lex.l" { return kw_FROM; } YY_BREAK case 31: YY_RULE_SETUP -#line 93 "lex.l" +#line 99 "lex.l" { return kw_GeneralString; } YY_BREAK case 32: YY_RULE_SETUP -#line 94 "lex.l" +#line 100 "lex.l" { return kw_GeneralizedTime; } YY_BREAK case 33: YY_RULE_SETUP -#line 95 "lex.l" +#line 101 "lex.l" { return kw_GraphicString; } YY_BREAK case 34: YY_RULE_SETUP -#line 96 "lex.l" +#line 102 "lex.l" { return kw_IA5String; } YY_BREAK case 35: YY_RULE_SETUP -#line 97 "lex.l" +#line 103 "lex.l" { return kw_IDENTIFIER; } YY_BREAK case 36: YY_RULE_SETUP -#line 98 "lex.l" +#line 104 "lex.l" { return kw_IMPLICIT; } YY_BREAK case 37: YY_RULE_SETUP -#line 99 "lex.l" +#line 105 "lex.l" { return kw_IMPLIED; } YY_BREAK case 38: YY_RULE_SETUP -#line 100 "lex.l" +#line 106 "lex.l" { return kw_IMPORTS; } YY_BREAK case 39: YY_RULE_SETUP -#line 101 "lex.l" +#line 107 "lex.l" { return kw_INCLUDES; } YY_BREAK case 40: YY_RULE_SETUP -#line 102 "lex.l" +#line 108 "lex.l" { return kw_INSTANCE; } YY_BREAK case 41: YY_RULE_SETUP -#line 103 "lex.l" +#line 109 "lex.l" { return kw_INTEGER; } YY_BREAK case 42: YY_RULE_SETUP -#line 104 "lex.l" +#line 110 "lex.l" { return kw_INTERSECTION; } YY_BREAK case 43: YY_RULE_SETUP -#line 105 "lex.l" +#line 111 "lex.l" { return kw_ISO646String; } YY_BREAK case 44: YY_RULE_SETUP -#line 106 "lex.l" +#line 112 "lex.l" { return kw_MAX; } YY_BREAK case 45: YY_RULE_SETUP -#line 107 "lex.l" +#line 113 "lex.l" { return kw_MIN; } YY_BREAK case 46: YY_RULE_SETUP -#line 108 "lex.l" +#line 114 "lex.l" { return kw_MINUS_INFINITY; } YY_BREAK case 47: YY_RULE_SETUP -#line 109 "lex.l" +#line 115 "lex.l" { return kw_NULL; } YY_BREAK case 48: YY_RULE_SETUP -#line 110 "lex.l" +#line 116 "lex.l" { return kw_NumericString; } YY_BREAK case 49: YY_RULE_SETUP -#line 111 "lex.l" +#line 117 "lex.l" { return kw_OBJECT; } YY_BREAK case 50: YY_RULE_SETUP -#line 112 "lex.l" +#line 118 "lex.l" { return kw_OCTET; } YY_BREAK case 51: YY_RULE_SETUP -#line 113 "lex.l" +#line 119 "lex.l" { return kw_OF; } YY_BREAK case 52: YY_RULE_SETUP -#line 114 "lex.l" +#line 120 "lex.l" { return kw_OPTIONAL; } YY_BREAK case 53: YY_RULE_SETUP -#line 115 "lex.l" +#line 121 "lex.l" { return kw_ObjectDescriptor; } YY_BREAK case 54: YY_RULE_SETUP -#line 116 "lex.l" +#line 122 "lex.l" { return kw_PATTERN; } YY_BREAK case 55: YY_RULE_SETUP -#line 117 "lex.l" +#line 123 "lex.l" { return kw_PDV; } YY_BREAK case 56: YY_RULE_SETUP -#line 118 "lex.l" +#line 124 "lex.l" { return kw_PLUS_INFINITY; } YY_BREAK case 57: YY_RULE_SETUP -#line 119 "lex.l" +#line 125 "lex.l" { return kw_PRESENT; } YY_BREAK case 58: YY_RULE_SETUP -#line 120 "lex.l" +#line 126 "lex.l" { return kw_PRIVATE; } YY_BREAK case 59: YY_RULE_SETUP -#line 121 "lex.l" +#line 127 "lex.l" { return kw_PrintableString; } YY_BREAK case 60: YY_RULE_SETUP -#line 122 "lex.l" +#line 128 "lex.l" { return kw_REAL; } YY_BREAK case 61: YY_RULE_SETUP -#line 123 "lex.l" +#line 129 "lex.l" { return kw_RELATIVE_OID; } YY_BREAK case 62: YY_RULE_SETUP -#line 124 "lex.l" +#line 130 "lex.l" { return kw_SEQUENCE; } YY_BREAK case 63: YY_RULE_SETUP -#line 125 "lex.l" +#line 131 "lex.l" { return kw_SET; } YY_BREAK case 64: YY_RULE_SETUP -#line 126 "lex.l" +#line 132 "lex.l" { return kw_SIZE; } YY_BREAK case 65: YY_RULE_SETUP -#line 127 "lex.l" +#line 133 "lex.l" { return kw_STRING; } YY_BREAK case 66: YY_RULE_SETUP -#line 128 "lex.l" +#line 134 "lex.l" { return kw_SYNTAX; } YY_BREAK case 67: YY_RULE_SETUP -#line 129 "lex.l" +#line 135 "lex.l" { return kw_T61String; } YY_BREAK case 68: YY_RULE_SETUP -#line 130 "lex.l" +#line 136 "lex.l" { return kw_TAGS; } YY_BREAK case 69: YY_RULE_SETUP -#line 131 "lex.l" +#line 137 "lex.l" { return kw_TRUE; } YY_BREAK case 70: YY_RULE_SETUP -#line 132 "lex.l" +#line 138 "lex.l" { return kw_TYPE_IDENTIFIER; } YY_BREAK case 71: YY_RULE_SETUP -#line 133 "lex.l" +#line 139 "lex.l" { return kw_TeletexString; } YY_BREAK case 72: YY_RULE_SETUP -#line 134 "lex.l" +#line 140 "lex.l" { return kw_UNION; } YY_BREAK case 73: YY_RULE_SETUP -#line 135 "lex.l" +#line 141 "lex.l" { return kw_UNIQUE; } YY_BREAK case 74: YY_RULE_SETUP -#line 136 "lex.l" +#line 142 "lex.l" { return kw_UNIVERSAL; } YY_BREAK case 75: YY_RULE_SETUP -#line 137 "lex.l" +#line 143 "lex.l" { return kw_UTCTime; } YY_BREAK case 76: YY_RULE_SETUP -#line 138 "lex.l" +#line 144 "lex.l" { return kw_UTF8String; } YY_BREAK case 77: YY_RULE_SETUP -#line 139 "lex.l" +#line 145 "lex.l" { return kw_UniversalString; } YY_BREAK case 78: YY_RULE_SETUP -#line 140 "lex.l" +#line 146 "lex.l" { return kw_VideotexString; } YY_BREAK case 79: YY_RULE_SETUP -#line 141 "lex.l" +#line 147 "lex.l" { return kw_VisibleString; } YY_BREAK case 80: YY_RULE_SETUP -#line 142 "lex.l" +#line 148 "lex.l" { return kw_WITH; } YY_BREAK case 81: YY_RULE_SETUP -#line 143 "lex.l" +#line 149 "lex.l" { return *yytext; } YY_BREAK case 82: YY_RULE_SETUP -#line 144 "lex.l" +#line 150 "lex.l" { return *yytext; } YY_BREAK case 83: YY_RULE_SETUP -#line 145 "lex.l" +#line 151 "lex.l" { return *yytext; } YY_BREAK case 84: YY_RULE_SETUP -#line 146 "lex.l" +#line 152 "lex.l" { return EEQUAL; } YY_BREAK case 85: YY_RULE_SETUP -#line 147 "lex.l" +#line 153 "lex.l" { int c, start_lineno = lineno; int f = 0; @@ -1534,7 +1451,7 @@ YY_RULE_SETUP YY_BREAK case 86: YY_RULE_SETUP -#line 166 "lex.l" +#line 172 "lex.l" { int c, start_lineno = lineno; int level = 1; @@ -1578,7 +1495,7 @@ YY_RULE_SETUP YY_BREAK case 87: YY_RULE_SETUP -#line 206 "lex.l" +#line 212 "lex.l" { int start_lineno = lineno; int c; @@ -1626,7 +1543,7 @@ YY_RULE_SETUP YY_BREAK case 88: YY_RULE_SETUP -#line 251 "lex.l" +#line 257 "lex.l" { char *e, *y = yytext; yylval.constant = strtol((const char *)yytext, &e, 0); @@ -1638,7 +1555,7 @@ YY_RULE_SETUP YY_BREAK case 89: YY_RULE_SETUP -#line 259 "lex.l" +#line 265 "lex.l" { yylval.name = estrdup ((const char *)yytext); return IDENTIFIER; @@ -1646,62 +1563,61 @@ YY_RULE_SETUP YY_BREAK case 90: YY_RULE_SETUP -#line 263 "lex.l" +#line 269 "lex.l" ; YY_BREAK case 91: -/* rule 91 can match eol */ YY_RULE_SETUP -#line 264 "lex.l" +#line 270 "lex.l" { ++lineno; } YY_BREAK case 92: YY_RULE_SETUP -#line 265 "lex.l" +#line 271 "lex.l" { return ELLIPSIS; } YY_BREAK case 93: YY_RULE_SETUP -#line 266 "lex.l" +#line 272 "lex.l" { return RANGE; } YY_BREAK case 94: YY_RULE_SETUP -#line 267 "lex.l" +#line 273 "lex.l" { error_message("Ignoring char(%c)\n", *yytext); } YY_BREAK case 95: YY_RULE_SETUP -#line 268 "lex.l" +#line 274 "lex.l" ECHO; YY_BREAK -#line 1678 "lex.yy.c" +#line 1595 "lex.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = (yy_hold_char); + *yy_cp = yy_hold_char; YY_RESTORE_YY_MORE_OFFSET - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our + * consistency between yy_current_buffer and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position @@ -1711,13 +1627,13 @@ case YY_STATE_EOF(INITIAL): * end-of-buffer state). Contrast this with the test * in input(). */ - if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; - (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; - yy_current_state = yy_get_previous_state( ); + yy_current_state = yy_get_previous_state(); /* Okay, we're now positioned to make the NUL * transition. We couldn't have @@ -1730,30 +1646,30 @@ case YY_STATE_EOF(INITIAL): yy_next_state = yy_try_NUL_trans( yy_current_state ); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; + yy_bp = yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ - yy_cp = ++(yy_c_buf_p); + yy_cp = ++yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { - yy_cp = (yy_c_buf_p); + yy_cp = yy_c_buf_p; goto yy_find_action; } } - else switch ( yy_get_next_buffer( ) ) + else switch ( yy_get_next_buffer() ) { case EOB_ACT_END_OF_FILE: { - (yy_did_buffer_switch_on_eof) = 0; + yy_did_buffer_switch_on_eof = 0; - if ( yywrap( ) ) + if ( yywrap() ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up @@ -1764,7 +1680,7 @@ case YY_STATE_EOF(INITIAL): * YY_NULL, it'll still work - another * YY_NULL will get returned. */ - (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; @@ -1772,30 +1688,30 @@ case YY_STATE_EOF(INITIAL): else { - if ( ! (yy_did_buffer_switch_on_eof) ) + if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = - (yytext_ptr) + yy_amount_of_matched_text; + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; - yy_current_state = yy_get_previous_state( ); + yy_current_state = yy_get_previous_state(); - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: - (yy_c_buf_p) = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; - yy_current_state = yy_get_previous_state( ); + yy_current_state = yy_get_previous_state(); - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; @@ -1806,7 +1722,8 @@ case YY_STATE_EOF(INITIAL): "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ -} /* end of yylex */ + } /* end of yylex */ + /* yy_get_next_buffer - try to read in a new buffer * @@ -1815,20 +1732,21 @@ case YY_STATE_EOF(INITIAL): * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ -static int yy_get_next_buffer (void) -{ - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = (yytext_ptr); + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; register int number_to_move, i; int ret_val; - if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + if ( yy_current_buffer->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. @@ -1848,30 +1766,34 @@ static int yy_get_next_buffer (void) /* Try to read more data. */ /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + yy_current_buffer->yy_n_chars = yy_n_chars = 0; else { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + YY_BUFFER_STATE b = yy_current_buffer; int yy_c_buf_p_offset = - (int) ((yy_c_buf_p) - b->yy_ch_buf); + (int) (yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { @@ -1884,7 +1806,8 @@ static int yy_get_next_buffer (void) b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ - yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ @@ -1894,35 +1817,35 @@ static int yy_get_next_buffer (void) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); - (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; - +#endif } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + yy_current_buffer->yy_n_chars = yy_n_chars; } - if ( (yy_n_chars) == 0 ) + if ( yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; - yyrestart(yyin ); + yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + yy_current_buffer->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } @@ -1930,31 +1853,32 @@ static int yy_get_next_buffer (void) else ret_val = EOB_ACT_CONTINUE_SCAN; - (yy_n_chars) += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; - (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; return ret_val; -} + } + /* yy_get_previous_state - get the state just before the EOB char was reached */ - static yy_state_type yy_get_previous_state (void) -{ +static yy_state_type yy_get_previous_state() + { register yy_state_type yy_current_state; register char *yy_cp; - - yy_current_state = (yy_start); - for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { @@ -1966,23 +1890,30 @@ static int yy_get_next_buffer (void) } return yy_current_state; -} + } + /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) -{ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { register int yy_is_jam; - register char *yy_cp = (yy_c_buf_p); + register char *yy_cp = yy_c_buf_p; register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { @@ -1994,73 +1925,81 @@ static int yy_get_next_buffer (void) yy_is_jam = (yy_current_state == 567); return yy_is_jam ? 0 : yy_current_state; -} + } - static void yyunput (int c, register char * yy_bp ) -{ - register char *yy_cp; - - yy_cp = (yy_c_buf_p); + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; /* undo effects of setting up yytext */ - *yy_cp = (yy_hold_char); + *yy_cp = yy_hold_char; - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ - register int number_to_move = (yy_n_chars) + 2; - register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; register char *source = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + &yy_current_buffer->yy_ch_buf[number_to_move]; - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + while ( source > yy_current_buffer->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; - (yytext_ptr) = yy_bp; - (yy_hold_char) = *yy_cp; - (yy_c_buf_p) = yy_cp; -} + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + #ifndef YY_NO_INPUT #ifdef __cplusplus - static int yyinput (void) +static int yyinput() #else - static int input (void) +static int input() #endif - -{ + { int c; - - *(yy_c_buf_p) = (yy_hold_char); - if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ - if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) /* This was really a NUL. */ - *(yy_c_buf_p) = '\0'; + *yy_c_buf_p = '\0'; else { /* need more input */ - int offset = (yy_c_buf_p) - (yytext_ptr); - ++(yy_c_buf_p); + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; - switch ( yy_get_next_buffer( ) ) + switch ( yy_get_next_buffer() ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() @@ -2074,16 +2013,16 @@ static int yy_get_next_buffer (void) */ /* Reset buffer status. */ - yyrestart(yyin ); + yyrestart( yyin ); - /*FALLTHROUGH*/ + /* fall through */ case EOB_ACT_END_OF_FILE: { - if ( yywrap( ) ) + if ( yywrap() ) return EOF; - if ( ! (yy_did_buffer_switch_on_eof) ) + if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); @@ -2093,92 +2032,90 @@ static int yy_get_next_buffer (void) } case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = (yytext_ptr) + offset; + yy_c_buf_p = yytext_ptr + offset; break; } } } - c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve yytext */ - (yy_hold_char) = *++(yy_c_buf_p); + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + return c; -} -#endif /* ifndef YY_NO_INPUT */ + } +#endif /* YY_NO_INPUT */ -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void yyrestart (FILE * input_file ) -{ - - if ( ! YY_CURRENT_BUFFER ){ - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer(yyin,YY_BUF_SIZE ); +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); } - yy_init_buffer(YY_CURRENT_BUFFER,input_file ); - yy_load_buffer_state( ); -} -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * yypop_buffer_state(); - * yypush_buffer_state(new_buffer); - */ - yyensure_buffer_stack (); - if ( YY_CURRENT_BUFFER == new_buffer ) +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) return; - if ( YY_CURRENT_BUFFER ) + if ( yy_current_buffer ) { /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; } - YY_CURRENT_BUFFER_LVALUE = new_buffer; - yy_load_buffer_state( ); + yy_current_buffer = new_buffer; + yy_load_buffer_state(); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ - (yy_did_buffer_switch_on_eof) = 1; -} + yy_did_buffer_switch_on_eof = 1; + } -static void yy_load_buffer_state (void) -{ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - (yy_hold_char) = *(yy_c_buf_p); -} -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) -{ +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); @@ -2187,75 +2124,75 @@ static void yy_load_buffer_state (void) /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; - yy_init_buffer(b,file ); + yy_init_buffer( b, file ); return b; -} + } -/** Destroy the buffer. - * @param b a buffer created with yy_create_buffer() - * - */ - void yy_delete_buffer (YY_BUFFER_STATE b ) -{ - + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { if ( ! b ) return; - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) - yyfree((void *) b->yy_ch_buf ); + yy_flex_free( (void *) b->yy_ch_buf ); - yyfree((void *) b ); -} + yy_flex_free( (void *) b ); + } -#ifndef __cplusplus -extern int isatty (int ); -#endif /* __cplusplus */ - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a yyrestart() or at EOF. - */ - static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) -{ - int oerrno = errno; - - yy_flush_buffer(b ); + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; - /* If b is the current buffer, then yy_init_buffer was _probably_ - * called from yyrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } - - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; - - errno = oerrno; -} +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * - */ - void yy_flush_buffer (YY_BUFFER_STATE b ) -{ - if ( ! b ) + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) return; b->yy_n_chars = 0; @@ -2272,121 +2209,29 @@ extern int isatty (int ); b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; - if ( b == YY_CURRENT_BUFFER ) - yy_load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) -{ - if (new_buffer == NULL) - return; - - yyensure_buffer_stack(); - - /* This block is copied from yy_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - (yy_buffer_stack_top)++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from yy_switch_to_buffer. */ - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void yypop_buffer_state (void) -{ - if (!YY_CURRENT_BUFFER) - return; - - yy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - if ((yy_buffer_stack_top) > 0) - --(yy_buffer_stack_top); - - if (YY_CURRENT_BUFFER) { - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void yyensure_buffer_stack (void) -{ - int num_to_alloc; - - if (!(yy_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; - (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - ); - - memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - (yy_buffer_stack_max) = num_to_alloc; - (yy_buffer_stack_top) = 0; - return; + if ( b == yy_current_buffer ) + yy_load_buffer_state(); } - if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - - /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; - num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc - ((yy_buffer_stack), - num_to_alloc * sizeof(struct yy_buffer_state*) - ); - - /* zero only the new slots.*/ - memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); - (yy_buffer_stack_max) = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) -{ +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { YY_BUFFER_STATE b; - + if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; - b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); @@ -2400,51 +2245,56 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; - yy_switch_to_buffer(b ); + yy_switch_to_buffer( b ); return b; -} + } +#endif -/** Setup the input buffer state to scan a string. The next call to yylex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * yy_scan_bytes() instead. - */ -YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) -{ - - return yy_scan_bytes(yystr,strlen(yystr) ); -} -/** Setup the input buffer state to scan the given bytes. The next call to yylex() will - * scan from a @e copy of @a bytes. - * @param bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @a bytes. - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) -{ +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; - + /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; - buf = (char *) yyalloc(n ); + n = len + 2; + buf = (char *) yy_flex_alloc( n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; - b = yy_scan_buffer(buf,n ); + b = yy_scan_buffer( buf, n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); @@ -2454,196 +2304,148 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) b->yy_is_our_buffer = 1; return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 + } #endif -static void yy_fatal_error (yyconst char* msg ) -{ - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - yytext[yyleng] = (yy_hold_char); \ - (yy_c_buf_p) = yytext + yyless_macro_arg; \ - (yy_hold_char) = *(yy_c_buf_p); \ - *(yy_c_buf_p) = '\0'; \ - yyleng = yyless_macro_arg; \ - } \ - while ( 0 ) +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; -/* Accessor methods (get/set functions) to struct members. */ + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); -/** Get the current line number. - * - */ -int yyget_lineno (void) -{ - - return yylineno; -} + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); -/** Get the input stream. - * - */ -FILE *yyget_in (void) -{ - return yyin; -} + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); -/** Get the output stream. - * - */ -FILE *yyget_out (void) -{ - return yyout; -} + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } -/** Get the length of the current token. - * - */ -int yyget_leng (void) -{ - return yyleng; -} + yy_start_stack[yy_start_stack_ptr++] = YY_START; -/** Get the current token. - * - */ + BEGIN(new_state); + } +#endif -char *yyget_text (void) -{ - return yytext; -} -/** Set the current line number. - * @param line_number - * - */ -void yyset_lineno (int line_number ) -{ - - yylineno = line_number; -} +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); -/** Set the input stream. This does not discard the current - * input buffer. - * @param in_str A readable stream. - * - * @see yy_switch_to_buffer - */ -void yyset_in (FILE * in_str ) -{ - yyin = in_str ; -} + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif -void yyset_out (FILE * out_str ) -{ - yyout = out_str ; -} -int yyget_debug (void) -{ - return yy_flex_debug; -} +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif -void yyset_debug (int bdebug ) -{ - yy_flex_debug = bdebug ; -} +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif -static int yy_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from yylex_destroy(), so don't allocate here. - */ - - (yy_buffer_stack) = 0; - (yy_buffer_stack_top) = 0; - (yy_buffer_stack_max) = 0; - (yy_c_buf_p) = (char *) 0; - (yy_init) = 0; - (yy_start) = 0; - -/* Defined in main.c */ -#ifdef YY_STDINIT - yyin = stdin; - yyout = stdout; +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) #else - yyin = (FILE *) 0; - yyout = (FILE *) 0; +static void yy_fatal_error( msg ) +char msg[]; #endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } - /* For future reference: Set errno on error, since we are called by - * yylex_init() - */ - return 0; -} -/* yylex_destroy is for both reentrant and non-reentrant scanners. */ -int yylex_destroy (void) -{ - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - yy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - yypop_buffer_state(); - } - /* Destroy the stack itself. */ - yyfree((yy_buffer_stack) ); - (yy_buffer_stack) = NULL; +/* Redefine yyless() so it works in section 3 code. */ - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * yylex() is called, initialization will occur. */ - yy_init_globals( ); +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) - return 0; -} -/* - * Internal utility routines. - */ +/* Internal utility routines. */ #ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) -{ +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; -} + } #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s ) -{ +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { register int n; for ( n = 0; s[n]; ++n ) ; return n; -} + } #endif -void *yyalloc (yy_size_t size ) -{ + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { return (void *) malloc( size ); -} + } -void *yyrealloc (void * ptr, yy_size_t size ) -{ +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter @@ -2652,17 +2454,26 @@ void *yyrealloc (void * ptr, yy_size_t size ) * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); -} - -void yyfree (void * ptr ) -{ - free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" + } -#line 268 "lex.l" +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 274 "lex.l" #ifndef yywrap /* XXX */ @@ -2690,4 +2501,3 @@ unterminated(const char *type, unsigned start_lineno) { error_message("unterminated %s, possibly started on line %d\n", type, start_lineno); } - diff --git a/source4/heimdal/lib/asn1/main.c b/source4/heimdal/lib/asn1/main.c index eec775f3ba..bba79b1e4e 100644 --- a/source4/heimdal/lib/asn1/main.c +++ b/source4/heimdal/lib/asn1/main.c @@ -35,11 +35,12 @@ #include <getarg.h> #include "lex.h" -RCSID("$Id: main.c,v 1.15 2005/08/23 10:50:12 lha Exp $"); +RCSID("$Id: main.c,v 1.16 2006/09/05 12:27:29 lha Exp $"); extern FILE *yyin; static getarg_strings preserve; +static getarg_strings seq; int preserve_type(const char *p) @@ -51,6 +52,16 @@ preserve_type(const char *p) return 0; } +int +seq_type(const char *p) +{ + int i; + for (i = 0; i < seq.num_strings; i++) + if (strcmp(seq.strings[i], p) == 0) + return 1; + return 0; +} + int dce_fix; int rfc1510_bitstring; int version_flag; @@ -59,6 +70,7 @@ struct getargs args[] = { { "encode-rfc1510-bit-string", 0, arg_flag, &rfc1510_bitstring }, { "decode-dce-ber", 0, arg_flag, &dce_fix }, { "preserve-binary", 0, arg_strings, &preserve }, + { "sequence", 0, arg_strings, &seq }, { "version", 0, arg_flag, &version_flag }, { "help", 0, arg_flag, &help_flag } }; diff --git a/source4/heimdal/lib/asn1/parse.c b/source4/heimdal/lib/asn1/parse.c index e498d8f965..29d13ed68d 100644 --- a/source4/heimdal/lib/asn1/parse.c +++ b/source4/heimdal/lib/asn1/parse.c @@ -1,7 +1,7 @@ -/* A Bison parser, made by GNU Bison 2.0. */ +/* A Bison parser, made by GNU Bison 2.1. */ /* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,8 +15,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. @@ -36,6 +36,9 @@ /* Identify Bison output. */ #define YYBISON 1 +/* Bison version. */ +#define YYBISON_VERSION "2.1" + /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" @@ -142,6 +145,7 @@ NUMBER = 344 }; #endif +/* Tokens. */ #define kw_ABSENT 258 #define kw_ABSTRACT_SYNTAX 259 #define kw_ALL 260 @@ -277,6 +281,11 @@ struct string_list { # define YYERROR_VERBOSE 0 #endif +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) #line 65 "parse.y" typedef union YYSTYPE { @@ -293,8 +302,8 @@ typedef union YYSTYPE { struct memhead *members; struct constraint_spec *constraint_spec; } YYSTYPE; -/* Line 190 of yacc.c. */ -#line 298 "parse.c" +/* Line 196 of yacc.c. */ +#line 307 "parse.c" # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 @@ -305,17 +314,36 @@ typedef union YYSTYPE { /* Copy the second part of user declarations. */ -/* Line 213 of yacc.c. */ -#line 310 "parse.c" +/* Line 219 of yacc.c. */ +#line 319 "parse.c" -#if ! defined (yyoverflow) || YYERROR_VERBOSE +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) && (defined (__STDC__) || defined (__cplusplus)) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif -# ifndef YYFREE -# define YYFREE free +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif # endif -# ifndef YYMALLOC -# define YYMALLOC malloc +# ifndef YY_ +# define YY_(msgid) msgid # endif +#endif + +#if ! defined (yyoverflow) || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ @@ -325,6 +353,10 @@ typedef union YYSTYPE { # define YYSTACK_ALLOC __builtin_alloca # else # define YYSTACK_ALLOC alloca +# if defined (__STDC__) || defined (__cplusplus) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# define YYINCLUDED_STDLIB_H +# endif # endif # endif # endif @@ -332,13 +364,39 @@ typedef union YYSTYPE { # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# else -# if defined (__STDC__) || defined (__cplusplus) -# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2005 */ # endif +# else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1) +# endif +# ifdef __cplusplus +extern "C" { +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \ + && (defined (__STDC__) || defined (__cplusplus))) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \ + && (defined (__STDC__) || defined (__cplusplus))) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifdef __cplusplus +} +# endif # endif #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ @@ -373,7 +431,7 @@ union yyalloc # define YYCOPY(To, From, Count) \ do \ { \ - register YYSIZE_T yyi; \ + YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ @@ -423,7 +481,7 @@ union yyalloc #define YYUNDEFTOK 2 #define YYMAXUTOK 344 -#define YYTRANSLATE(YYX) \ +#define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ @@ -548,8 +606,8 @@ static const unsigned short int yyrline[] = }; #endif -#if YYDEBUG || YYERROR_VERBOSE -/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { @@ -804,22 +862,6 @@ static const unsigned char yystos[] = 154 }; -#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) -# define YYSIZE_T __SIZE_TYPE__ -#endif -#if ! defined (YYSIZE_T) && defined (size_t) -# define YYSIZE_T size_t -#endif -#if ! defined (YYSIZE_T) -# if defined (__STDC__) || defined (__cplusplus) -# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif -#endif -#if ! defined (YYSIZE_T) -# define YYSIZE_T unsigned int -#endif - #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) @@ -849,8 +891,8 @@ do \ goto yybackup; \ } \ else \ - { \ - yyerror ("syntax error: cannot back up");\ + { \ + yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (0) @@ -929,7 +971,7 @@ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ - yysymprint (stderr, \ + yysymprint (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ @@ -977,13 +1019,13 @@ yy_reduce_print (yyrule) #endif { int yyi; - unsigned int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu), ", yyrule - 1, yylno); /* Print the symbols being reduced, and their result. */ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) - YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); - YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, "-> %s\n", yytname[yyr1[yyrule]]); } # define YY_REDUCE_PRINT(Rule) \ @@ -1012,7 +1054,7 @@ int yydebug; if the built-in stack extension method is used). Do not make this value too large; the results are undefined if - SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH @@ -1036,7 +1078,7 @@ yystrlen (yystr) const char *yystr; # endif { - register const char *yys = yystr; + const char *yys = yystr; while (*yys++ != '\0') continue; @@ -1061,8 +1103,8 @@ yystpcpy (yydest, yysrc) const char *yysrc; # endif { - register char *yyd = yydest; - register const char *yys = yysrc; + char *yyd = yydest; + const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; @@ -1072,7 +1114,55 @@ yystpcpy (yydest, yysrc) # endif # endif -#endif /* !YYERROR_VERBOSE */ +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + size_t yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +#endif /* YYERROR_VERBOSE */ @@ -1197,8 +1287,8 @@ yyparse () #endif { - register int yystate; - register int yyn; + int yystate; + int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; @@ -1216,12 +1306,12 @@ yyparse () /* The state stack. */ short int yyssa[YYINITDEPTH]; short int *yyss = yyssa; - register short int *yyssp; + short int *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; - register YYSTYPE *yyvsp; + YYSTYPE *yyvsp; @@ -1253,9 +1343,6 @@ yyparse () yyssp = yyss; yyvsp = yyvs; - - yyvsp[0] = yylval; - goto yysetstate; /*------------------------------------------------------------. @@ -1288,7 +1375,7 @@ yyparse () data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ - yyoverflow ("parser stack overflow", + yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), @@ -1299,11 +1386,11 @@ yyparse () } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE - goto yyoverflowlab; + goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) - goto yyoverflowlab; + goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; @@ -1313,7 +1400,7 @@ yyparse () union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) - goto yyoverflowlab; + goto yyexhaustedlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); @@ -2143,10 +2230,11 @@ yyreduce: break; + default: break; } -/* Line 1037 of yacc.c. */ -#line 2150 "parse.c" +/* Line 1126 of yacc.c. */ +#line 2238 "parse.c" yyvsp -= yylen; yyssp -= yylen; @@ -2185,12 +2273,36 @@ yyerrlab: if (YYPACT_NINF < yyn && yyn < YYLAST) { - YYSIZE_T yysize = 0; int yytype = YYTRANSLATE (yychar); - const char* yyprefix; - char *yymsg; + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + char *yymsg = 0; +# define YYERROR_VERBOSE_ARGS_MAXIMUM 5 + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; +#if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +#endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; @@ -2198,48 +2310,68 @@ yyerrlab: /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 0; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); - yyprefix = ", expecting "; for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { - yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); - yycount += 1; - if (yycount == 5) + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { - yysize = 0; + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; break; } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= yysize1 < yysize; + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; } - yysize += (sizeof ("syntax error, unexpected ") - + yystrlen (yytname[yytype])); - yymsg = (char *) YYSTACK_ALLOC (yysize); - if (yymsg != 0) - { - char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); - yyp = yystpcpy (yyp, yytname[yytype]); - if (yycount < 5) + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= yysize1 < yysize; + yysize = yysize1; + + if (!yysize_overflow && yysize <= YYSTACK_ALLOC_MAXIMUM) + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yymsg; + int yyi = 0; + while ((*yyp = *yyf)) { - yyprefix = ", expecting "; - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - yyp = yystpcpy (yyp, yyprefix); - yyp = yystpcpy (yyp, yytname[yyx]); - yyprefix = " or "; - } + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } } yyerror (yymsg); YYSTACK_FREE (yymsg); } else - yyerror ("syntax error; also virtual memory exhausted"); + { + yyerror (YY_("syntax error")); + goto yyexhaustedlab; + } } else #endif /* YYERROR_VERBOSE */ - yyerror ("syntax error"); + yyerror (YY_("syntax error")); } @@ -2251,18 +2383,9 @@ yyerrlab: if (yychar <= YYEOF) { - /* If at end of input, pop the error token, - then the rest of the stack, then return failure. */ + /* Return failure if at end of input. */ if (yychar == YYEOF) - for (;;) - { - - YYPOPSTACK; - if (yyssp == yyss) - YYABORT; - yydestruct ("Error: popping", - yystos[*yyssp], yyvsp); - } + YYABORT; } else { @@ -2281,12 +2404,11 @@ yyerrlab: `---------------------------------------------------*/ yyerrorlab: -#ifdef __GNUC__ - /* Pacify GCC when the user code never invokes YYERROR and the label - yyerrorlab therefore never appears in user code. */ + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ if (0) goto yyerrorlab; -#endif yyvsp -= yylen; yyssp -= yylen; @@ -2349,23 +2471,29 @@ yyacceptlab: | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: - yydestruct ("Error: discarding lookahead", - yytoken, &yylval); - yychar = YYEMPTY; yyresult = 1; goto yyreturn; #ifndef yyoverflow -/*----------------------------------------------. -| yyoverflowlab -- parser overflow comes here. | -`----------------------------------------------*/ -yyoverflowlab: - yyerror ("parser stack overflow"); +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: + if (yychar != YYEOF && yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp); + YYPOPSTACK; + } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); diff --git a/source4/heimdal/lib/asn1/parse.h b/source4/heimdal/lib/asn1/parse.h index 5cc1342618..df4587501e 100644 --- a/source4/heimdal/lib/asn1/parse.h +++ b/source4/heimdal/lib/asn1/parse.h @@ -1,7 +1,7 @@ -/* A Bison parser, made by GNU Bison 2.0. */ +/* A Bison parser, made by GNU Bison 2.1. */ /* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,8 +15,8 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. @@ -118,6 +118,7 @@ NUMBER = 344 }; #endif +/* Tokens. */ #define kw_ABSENT 258 #define kw_ABSTRACT_SYNTAX 259 #define kw_ALL 260 @@ -225,8 +226,8 @@ typedef union YYSTYPE { struct memhead *members; struct constraint_spec *constraint_spec; } YYSTYPE; -/* Line 1318 of yacc.c. */ -#line 230 "parse.h" +/* Line 1447 of yacc.c. */ +#line 231 "parse.h" # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 diff --git a/source4/heimdal/lib/asn1/pkinit.asn1 b/source4/heimdal/lib/asn1/pkinit.asn1 new file mode 100644 index 0000000000..56d6611677 --- /dev/null +++ b/source4/heimdal/lib/asn1/pkinit.asn1 @@ -0,0 +1,161 @@ +-- $Id$ -- + +PKINIT DEFINITIONS ::= BEGIN + +IMPORTS EncryptionKey, PrincipalName, Realm, KerberosTime, Checksum FROM krb5 + IssuerAndSerialNumber, ContentInfo FROM cms + SubjectPublicKeyInfo, AlgorithmIdentifier FROM rfc2459 + heim_any FROM heim; + +id-pkinit OBJECT IDENTIFIER ::= + { iso (1) org (3) dod (6) internet (1) security (5) + kerberosv5 (2) pkinit (3) } + +id-pkauthdata OBJECT IDENTIFIER ::= { id-pkinit 1 } +id-pkdhkeydata OBJECT IDENTIFIER ::= { id-pkinit 2 } +id-pkrkeydata OBJECT IDENTIFIER ::= { id-pkinit 3 } +id-pkekuoid OBJECT IDENTIFIER ::= { id-pkinit 4 } +id-pkkdcekuoid OBJECT IDENTIFIER ::= { id-pkinit 5 } + +id-pkinit-san OBJECT IDENTIFIER ::= + { iso(1) org(3) dod(6) internet(1) security(5) kerberosv5(2) + x509-sanan(2) } + +id-pkinit-ms-san OBJECT IDENTIFIER ::= + { iso(1) org(3) dod(6) internet(1) foo1(4) + foo2(1) foo3(311) foo4(20) foo5(2) foo6(3) } + +pa-pk-as-req INTEGER ::= 16 +pa-pk-as-rep INTEGER ::= 17 + +ad-initial-verified-cas INTEGER ::= 9 + +td-trusted-certifiers INTEGER ::= 104 +td-invalid-certificates INTEGER ::= 105 +td-dh-parameters INTEGER ::= 109 + +DHNonce ::= OCTET STRING + +TrustedCA ::= SEQUENCE { + caName [0] IMPLICIT OCTET STRING, + certificateSerialNumber [1] INTEGER OPTIONAL, + subjectKeyIdentifier [2] OCTET STRING OPTIONAL, + ... +} + +ExternalPrincipalIdentifier ::= SEQUENCE { + subjectName [0] IMPLICIT OCTET STRING OPTIONAL, + issuerAndSerialNumber [1] IMPLICIT OCTET STRING OPTIONAL, + subjectKeyIdentifier [2] IMPLICIT OCTET STRING OPTIONAL, + ... +} + +ExternalPrincipalIdentifiers ::= SEQUENCE OF ExternalPrincipalIdentifier + +PA-PK-AS-REQ ::= SEQUENCE { + signedAuthPack [0] IMPLICIT OCTET STRING, + trustedCertifiers [1] ExternalPrincipalIdentifiers OPTIONAL, + kdcPkId [2] IMPLICIT OCTET STRING OPTIONAL, + ... +} + +PKAuthenticator ::= SEQUENCE { + cusec [0] INTEGER -- (0..999999) --, + ctime [1] KerberosTime, + nonce [2] INTEGER (0..4294967295), + paChecksum [3] OCTET STRING OPTIONAL, + ... +} + +AuthPack ::= SEQUENCE { + pkAuthenticator [0] PKAuthenticator, + clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL, + supportedCMSTypes [2] SEQUENCE OF AlgorithmIdentifier OPTIONAL, + clientDHNonce [3] DHNonce OPTIONAL, + ... +} + +TD-TRUSTED-CERTIFIERS ::= ExternalPrincipalIdentifiers +TD-INVALID-CERTIFICATES ::= ExternalPrincipalIdentifiers + +KRB5PrincipalName ::= SEQUENCE { + realm [0] Realm, + principalName [1] PrincipalName +} + +AD-INITIAL-VERIFIED-CAS ::= SEQUENCE OF ExternalPrincipalIdentifier + + +DHRepInfo ::= SEQUENCE { + dhSignedData [0] IMPLICIT OCTET STRING, + serverDHNonce [1] DHNonce OPTIONAL +} + +PA-PK-AS-REP ::= CHOICE { + dhInfo [0] DHRepInfo, + encKeyPack [1] IMPLICIT OCTET STRING, + ... +} + +KDCDHKeyInfo ::= SEQUENCE { + subjectPublicKey [0] BIT STRING, + nonce [1] INTEGER (0..4294967295), + dhKeyExpiration [2] KerberosTime OPTIONAL, + ... +} + +ReplyKeyPack ::= SEQUENCE { + replyKey [0] EncryptionKey, + asChecksum [1] Checksum, + ... +} + +TD-DH-PARAMETERS ::= SEQUENCE OF AlgorithmIdentifier + + +-- Windows compat glue -- + +PKAuthenticator-Win2k ::= SEQUENCE { + kdcName [0] PrincipalName, + kdcRealm [1] Realm, + cusec [2] INTEGER (0..4294967295), + ctime [3] KerberosTime, + nonce [4] INTEGER (-2147483648..2147483647) +} + +AuthPack-Win2k ::= SEQUENCE { + pkAuthenticator [0] PKAuthenticator-Win2k, + clientPublicValue [1] SubjectPublicKeyInfo OPTIONAL +} + + +TrustedCA-Win2k ::= CHOICE { + caName [1] heim_any, + issuerAndSerial [2] IssuerAndSerialNumber +} + +PA-PK-AS-REQ-Win2k ::= SEQUENCE { + signed-auth-pack [0] IMPLICIT OCTET STRING, + trusted-certifiers [2] SEQUENCE OF TrustedCA-Win2k OPTIONAL, + kdc-cert [3] IMPLICIT OCTET STRING OPTIONAL, + encryption-cert [4] IMPLICIT OCTET STRING OPTIONAL +} + +PA-PK-AS-REP-Win2k ::= CHOICE { + dhSignedData [0] IMPLICIT OCTET STRING, + encKeyPack [1] IMPLICIT OCTET STRING +} + + +KDCDHKeyInfo-Win2k ::= SEQUENCE { + nonce [0] INTEGER (-2147483648..2147483647), + subjectPublicKey [2] BIT STRING +} + +ReplyKeyPack-Win2k ::= SEQUENCE { + replyKey [0] EncryptionKey, + nonce [1] INTEGER (0..4294967295), + ... +} + +END diff --git a/source4/heimdal/lib/asn1/rfc2459.asn1 b/source4/heimdal/lib/asn1/rfc2459.asn1 new file mode 100644 index 0000000000..eebbc3211b --- /dev/null +++ b/source4/heimdal/lib/asn1/rfc2459.asn1 @@ -0,0 +1,426 @@ +-- $Id$ -- +-- Definitions from rfc2459/rfc3280 + +RFC2459 DEFINITIONS ::= BEGIN + +IMPORTS heim_any FROM heim; + +Version ::= INTEGER { + rfc3280_version_1(0), + rfc3280_version_2(1), + rfc3280_version_3(2) +} + +id-pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + rsadsi(113549) pkcs(1) 1 } +id-pkcs1-rsaEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 1 } +id-pkcs1-md2WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 2 } +id-pkcs1-md5WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 4 } +id-pkcs1-sha1WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 5 } +id-pkcs1-sha256WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 11 } +id-pkcs1-sha384WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 12 } +id-pkcs1-sha512WithRSAEncryption OBJECT IDENTIFIER ::= { id-pkcs-1 13 } + +id-pkcs-2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + rsadsi(113549) pkcs(1) 2 } +id-pkcs2-md2 OBJECT IDENTIFIER ::= { id-pkcs-2 2 } +id-pkcs2-md4 OBJECT IDENTIFIER ::= { id-pkcs-2 4 } +id-pkcs2-md5 OBJECT IDENTIFIER ::= { id-pkcs-2 5 } + +id-rsa-digestAlgorithm OBJECT IDENTIFIER ::= +{ iso(1) member-body(2) us(840) rsadsi(113549) 2 } + +id-rsa-digest-md2 OBJECT IDENTIFIER ::= { id-rsa-digestAlgorithm 2 } +id-rsa-digest-md4 OBJECT IDENTIFIER ::= { id-rsa-digestAlgorithm 4 } +id-rsa-digest-md5 OBJECT IDENTIFIER ::= { id-rsa-digestAlgorithm 5 } + +id-pkcs-3 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + rsadsi(113549) pkcs(1) 3 } + +id-pkcs3-rc2-cbc OBJECT IDENTIFIER ::= { id-pkcs-3 2 } +id-pkcs3-rc4 OBJECT IDENTIFIER ::= { id-pkcs-3 4 } +id-pkcs3-des-ede3-cbc OBJECT IDENTIFIER ::= { id-pkcs-3 7 } + +id-rsadsi-encalg OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) + rsadsi(113549) 3 } + +id-rsadsi-rc2-cbc OBJECT IDENTIFIER ::= { id-rsadsi-encalg 2 } +id-rsadsi-des-ede3-cbc OBJECT IDENTIFIER ::= { id-rsadsi-encalg 7 } + +id-secsig-sha-1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) + oiw(14) secsig(3) algorithm(2) 26 } + +id-nistAlgorithm OBJECT IDENTIFIER ::= { + joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) 4 } + +id-nist-aes-algs OBJECT IDENTIFIER ::= { id-nistAlgorithm 1 } + +id-aes-128-cbc OBJECT IDENTIFIER ::= { id-nist-aes-algs 2 } +id-aes-192-cbc OBJECT IDENTIFIER ::= { id-nist-aes-algs 22 } +id-aes-256-cbc OBJECT IDENTIFIER ::= { id-nist-aes-algs 42 } + +id-nist-sha-algs OBJECT IDENTIFIER ::= { id-nistAlgorithm 2 } + +id-sha256 OBJECT IDENTIFIER ::= { id-nist-sha-algs 1 } +id-sha224 OBJECT IDENTIFIER ::= { id-nist-sha-algs 4 } +id-sha384 OBJECT IDENTIFIER ::= { id-nist-sha-algs 2 } +id-sha512 OBJECT IDENTIFIER ::= { id-nist-sha-algs 3 } + +id-dhpublicnumber OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) ansi-x942(10046) + number-type(2) 1 } + +id-x9-57 OBJECT IDENTIFIER ::= { + iso(1) member-body(2) us(840) ansi-x942(10046) + 4 } + +id-dsa OBJECT IDENTIFIER ::= { id-x9-57 1 } +id-dsa-with-sha1 OBJECT IDENTIFIER ::= { id-x9-57 3 } + +-- x.520 names types + +id-x520-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 } + +id-at-commonName OBJECT IDENTIFIER ::= { id-x520-at 3 } +id-at-surname OBJECT IDENTIFIER ::= { id-x520-at 4 } +id-at-serialNumber OBJECT IDENTIFIER ::= { id-x520-at 5 } +id-at-countryName OBJECT IDENTIFIER ::= { id-x520-at 6 } +id-at-localityName OBJECT IDENTIFIER ::= { id-x520-at 7 } +id-at-stateOrProvinceName OBJECT IDENTIFIER ::= { id-x520-at 8 } +id-at-organizationName OBJECT IDENTIFIER ::= { id-x520-at 10 } +id-at-organizationalUnitName OBJECT IDENTIFIER ::= { id-x520-at 11 } +id-at-name OBJECT IDENTIFIER ::= { id-x520-at 41 } +id-at-givenName OBJECT IDENTIFIER ::= { id-x520-at 42 } +id-at-initials OBJECT IDENTIFIER ::= { id-x520-at 43 } +id-at-generationQualifier OBJECT IDENTIFIER ::= { id-x520-at 44 } +id-at-pseudonym OBJECT IDENTIFIER ::= { id-x520-at 65 } +-- RFC 2247 +id-Userid OBJECT IDENTIFIER ::= + { 0 9 2342 19200300 100 1 1 } +id-domainComponent OBJECT IDENTIFIER ::= + { 0 9 2342 19200300 100 1 25 } + + +-- rfc3280 + +id-x509-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} + +AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters heim_any OPTIONAL +} + +AttributeType ::= OBJECT IDENTIFIER + +AttributeValue ::= heim_any + +TeletexStringx ::= [UNIVERSAL 20] IMPLICIT OCTET STRING + +DirectoryString ::= CHOICE { + ia5String IA5String, + teletexString TeletexStringx, + printableString PrintableString, + universalString UniversalString, + utf8String UTF8String, + bmpString BMPString +} + +Attribute ::= SEQUENCE { + type AttributeType, + value SET OF -- AttributeValue -- heim_any +} + +AttributeTypeAndValue ::= SEQUENCE { + type AttributeType, + value DirectoryString +} + +RelativeDistinguishedName ::= SET OF AttributeTypeAndValue + +RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + +Name ::= CHOICE { + rdnSequence RDNSequence +} + +CertificateSerialNumber ::= INTEGER + +Time ::= CHOICE { + utcTime UTCTime, + generalTime GeneralizedTime +} + +Validity ::= SEQUENCE { + notBefore Time, + notAfter Time +} + +UniqueIdentifier ::= BIT STRING + +SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING +} + +Extension ::= SEQUENCE { + extnID OBJECT IDENTIFIER, + critical BOOLEAN OPTIONAL, -- DEFAULT FALSE XXX + extnValue OCTET STRING +} + +Extensions ::= SEQUENCE OF Extension -- SIZE (1..MAX) + +TBSCertificate ::= SEQUENCE { + version [0] Version OPTIONAL, -- EXPLICIT nnn DEFAULT 1, + serialNumber CertificateSerialNumber, + signature AlgorithmIdentifier, + issuer Name, + validity Validity, + subject Name, + subjectPublicKeyInfo SubjectPublicKeyInfo, + issuerUniqueID [1] IMPLICIT BIT STRING -- UniqueIdentifier -- OPTIONAL, + -- If present, version shall be v2 or v3 + subjectUniqueID [2] IMPLICIT BIT STRING -- UniqueIdentifier -- OPTIONAL, + -- If present, version shall be v2 or v3 + extensions [3] EXPLICIT Extensions OPTIONAL + -- If present, version shall be v3 +} + +Certificate ::= SEQUENCE { + tbsCertificate TBSCertificate, + signatureAlgorithm AlgorithmIdentifier, + signatureValue BIT STRING +} + +Certificates ::= SEQUENCE OF Certificate + +ValidationParms ::= SEQUENCE { + seed BIT STRING, + pgenCounter INTEGER +} + +DomainParameters ::= SEQUENCE { + p INTEGER, -- odd prime, p=jq +1 + g INTEGER, -- generator, g + q INTEGER, -- factor of p-1 + j INTEGER OPTIONAL, -- subgroup factor + validationParms ValidationParms OPTIONAL -- ValidationParms +} + +DHPublicKey ::= INTEGER + +OtherName ::= SEQUENCE { + type-id OBJECT IDENTIFIER, + value [0] EXPLICIT heim_any +} + +GeneralName ::= CHOICE { + otherName [0] IMPLICIT -- OtherName -- SEQUENCE { + type-id OBJECT IDENTIFIER, + value [0] EXPLICIT heim_any + }, + rfc822Name [1] IMPLICIT IA5String, + dNSName [2] IMPLICIT IA5String, +-- x400Address [3] IMPLICIT ORAddress,-- + directoryName [4] IMPLICIT -- Name -- CHOICE { + rdnSequence RDNSequence + }, +-- ediPartyName [5] IMPLICIT EDIPartyName, -- + uniformResourceIdentifier [6] IMPLICIT IA5String, + iPAddress [7] IMPLICIT OCTET STRING, + registeredID [8] IMPLICIT OBJECT IDENTIFIER +} + +GeneralNames ::= SEQUENCE -- SIZE (1..MAX) -- OF GeneralName + +id-x509-ce-keyUsage OBJECT IDENTIFIER ::= { id-x509-ce 15 } + +KeyUsage ::= BIT STRING { + digitalSignature (0), + nonRepudiation (1), + keyEncipherment (2), + dataEncipherment (3), + keyAgreement (4), + keyCertSign (5), + cRLSign (6), + encipherOnly (7), + decipherOnly (8) +} + +id-x509-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-x509-ce 35 } + +KeyIdentifier ::= OCTET STRING + +AuthorityKeyIdentifier ::= SEQUENCE { + keyIdentifier [0] IMPLICIT OCTET STRING OPTIONAL, + authorityCertIssuer [1] IMPLICIT -- GeneralName -- + SEQUENCE -- SIZE (1..MAX) -- OF GeneralName OPTIONAL, + authorityCertSerialNumber [2] IMPLICIT INTEGER OPTIONAL +} + +id-x509-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-x509-ce 14 } + +SubjectKeyIdentifier ::= KeyIdentifier + +id-x509-ce-basicConstraints OBJECT IDENTIFIER ::= { id-x509-ce 19 } + +BasicConstraints ::= SEQUENCE { + cA BOOLEAN OPTIONAL -- DEFAULT FALSE --, + pathLenConstraint INTEGER (0..4294967295) OPTIONAL +} + +id-x509-ce-nameConstraints OBJECT IDENTIFIER ::= { id-x509-ce 30 } + +BaseDistance ::= INTEGER -- (0..MAX) -- + +GeneralSubtree ::= SEQUENCE { + base GeneralName, + minimum [0] IMPLICIT -- BaseDistance -- INTEGER OPTIONAL -- DEFAULT 0 --, + maximum [1] IMPLICIT -- BaseDistance -- INTEGER OPTIONAL +} + +GeneralSubtrees ::= SEQUENCE -- SIZE (1..MAX) -- OF GeneralSubtree + +NameConstraints ::= SEQUENCE { + permittedSubtrees [0] IMPLICIT -- GeneralSubtrees -- SEQUENCE OF GeneralSubtree OPTIONAL, + excludedSubtrees [1] IMPLICIT -- GeneralSubtrees -- SEQUENCE OF GeneralSubtree OPTIONAL +} + +id-x509-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::= { id-x509-ce 16 } +id-x509-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-x509-ce 32 } +id-x509-ce-policyMappings OBJECT IDENTIFIER ::= { id-x509-ce 33 } +id-x509-ce-subjectAltName OBJECT IDENTIFIER ::= { id-x509-ce 17 } +id-x509-ce-issuerAltName OBJECT IDENTIFIER ::= { id-x509-ce 18 } +id-x509-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-x509-ce 9 } +id-x509-ce-policyConstraints OBJECT IDENTIFIER ::= { id-x509-ce 36 } + +id-x509-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-x509-ce 37} + +ExtKeyUsage ::= SEQUENCE OF OBJECT IDENTIFIER + +id-x509-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-x509-ce 31 } +id-x509-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-x509-ce 27 } +id-x509-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-x509-ce 28 } +id-x509-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-x509-ce 23 } +id-x509-ce-invalidityDate OBJECT IDENTIFIER ::= { id-x509-ce 24 } +id-x509-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-x509-ce 29 } +id-x509-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-x509-ce 54 } + +-- rfc3279 + +DSASigValue ::= SEQUENCE { + r INTEGER, + s INTEGER +} + +DSAPublicKey ::= INTEGER + +DSAParams ::= SEQUENCE { + p INTEGER, + q INTEGER, + g INTEGER +} + +-- really pkcs1 + +RSAPublicKey ::= SEQUENCE { + modulus INTEGER, -- n + publicExponent INTEGER -- e +} + +RSAPrivateKey ::= SEQUENCE { + version INTEGER (0..4294967295), + modulus INTEGER, -- n + publicExponent INTEGER, -- e + privateExponent INTEGER, -- d + prime1 INTEGER, -- p + prime2 INTEGER, -- q + exponent1 INTEGER, -- d mod (p-1) + exponent2 INTEGER, -- d mod (q-1) + coefficient INTEGER -- (inverse of q) mod p +} + +DigestInfo ::= SEQUENCE { + digestAlgorithm AlgorithmIdentifier, + digest OCTET STRING +} + +-- some ms ext + +-- szOID_ENROLL_CERTTYPE_EXTENSION "1.3.6.1.4.1.311.20.2" is Encoded as a + +-- UNICODESTRING (0x1E tag) + +-- szOID_CERTIFICATE_TEMPLATE "1.3.6.1.4.1.311.21.7" is Encoded as: + +-- TemplateVersion ::= INTEGER (0..4294967295) + +-- CertificateTemplate ::= SEQUENCE { +-- templateID OBJECT IDENTIFIER, +-- templateMajorVersion TemplateVersion, +-- templateMinorVersion TemplateVersion OPTIONAL +-- } + + +-- +-- CRL +-- + +TBSCRLCertList ::= SEQUENCE { + version Version OPTIONAL, -- if present, MUST be v2 + signature AlgorithmIdentifier, + issuer Name, + thisUpdate Time, + nextUpdate Time OPTIONAL, + revokedCertificates SEQUENCE OF SEQUENCE { + userCertificate CertificateSerialNumber, + revocationDate Time, + crlEntryExtensions Extensions OPTIONAL + -- if present, MUST be v2 + } OPTIONAL, + crlExtensions [0] EXPLICIT Extensions OPTIONAL + -- if present, MUST be v2 +} + + +CRLCertificateList ::= SEQUENCE { + tbsCertList TBSCRLCertList, + signatureAlgorithm AlgorithmIdentifier, + signatureValue BIT STRING +} + +id-x509-ce-cRLNumber OBJECT IDENTIFIER ::= { id-x509-ce 20 } +id-x509-ce-freshestCRL OBJECT IDENTIFIER ::= { id-x509-ce 46 } +id-x509-ce-cRLReason OBJECT IDENTIFIER ::= { id-x509-ce 21 } + +CRLReason ::= ENUMERATED { + unspecified (0), + keyCompromise (1), + cACompromise (2), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5), + certificateHold (6), + removeFromCRL (8), + privilegeWithdrawn (9), + aACompromise (10) +} + +-- RFC 3820 Proxy Certificate Profile + +id-pkix-pe OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) + dod(6) internet(1) security(5) mechanisms(5) pkix(7) 1 } + +id-pe-proxyCertInfo OBJECT IDENTIFIER ::= { id-pkix-pe 14 } + +ProxyPolicy ::= SEQUENCE { + policyLanguage OBJECT IDENTIFIER, + policy OCTET STRING OPTIONAL +} + +ProxyCertInfo ::= SEQUENCE { + pCPathLenConstraint INTEGER (0..4294967295) OPTIONAL, -- really MAX + proxyPolicy ProxyPolicy +} + +END diff --git a/source4/heimdal/lib/asn1/test.asn1 b/source4/heimdal/lib/asn1/test.asn1 index 22fcc0b003..1a1179bc30 100644 --- a/source4/heimdal/lib/asn1/test.asn1 +++ b/source4/heimdal/lib/asn1/test.asn1 @@ -1,4 +1,4 @@ --- $Id: test.asn1,v 1.8 2006/01/31 09:42:04 lha Exp $ -- +-- $Id: test.asn1,v 1.9 2006/09/05 14:00:44 lha Exp $ -- TEST DEFINITIONS ::= @@ -83,4 +83,6 @@ TESTUSERCONSTRAINED ::= OCTET STRING (CONSTRAINED BY { -- meh -- }) -- TESTUSERCONSTRAINED3 ::= OCTET STRING (CONSTRAINED BY { INTEGER }) -- TESTUSERCONSTRAINED4 ::= OCTET STRING (CONSTRAINED BY { INTEGER : 1 }) +TESTSeqOf ::= SEQUENCE OF TESTInteger + END diff --git a/source4/heimdal/lib/asn1/timegm.c b/source4/heimdal/lib/asn1/timegm.c new file mode 100644 index 0000000000..86df58d700 --- /dev/null +++ b/source4/heimdal/lib/asn1/timegm.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "der_locl.h" + +RCSID("$Id: timegm.c,v 1.11 2006/10/19 16:19:32 lha Exp $"); + +static int +is_leap(unsigned y) +{ + y += 1900; + return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0); +} + +/* + * This is a simplifed version of _der_timegm that doesn't accept out + * of bound values that timegm(3) normally accepts but those are not + * valid in asn1 encodings. + */ + +time_t +_der_timegm (struct tm *tm) +{ + static const unsigned ndays[2][12] ={ + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, + {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}}; + time_t res = 0; + unsigned i; + + if (tm->tm_year < 0) + return -1; + if (tm->tm_mon < 0 || tm->tm_mon > 11) + return -1; + if (tm->tm_mday < 1 || tm->tm_mday > ndays[is_leap(tm->tm_year)][tm->tm_mon]) + return -1; + if (tm->tm_hour < 0 || tm->tm_hour > 23) + return -1; + if (tm->tm_min < 0 || tm->tm_min > 59) + return -1; + if (tm->tm_sec < 0 || tm->tm_sec > 59) + return -1; + + for (i = 70; i < tm->tm_year; ++i) + res += is_leap(i) ? 366 : 365; + + for (i = 0; i < tm->tm_mon; ++i) + res += ndays[is_leap(tm->tm_year)][i]; + res += tm->tm_mday - 1; + res *= 24; + res += tm->tm_hour; + res *= 60; + res += tm->tm_min; + res *= 60; + res += tm->tm_sec; + return res; +} diff --git a/source4/heimdal/lib/com_err/lex.c b/source4/heimdal/lib/com_err/lex.c index 4697d0a3fd..30b44d0c19 100644 --- a/source4/heimdal/lib/com_err/lex.c +++ b/source4/heimdal/lib/com_err/lex.c @@ -1,94 +1,32 @@ -#include "config.h" - -#line 3 "lex.yy.c" - -#define YY_INT_ALIGNED short int - /* A lexical scanner generated by flex */ +/* Scanner skeleton version: + * $Header: /cvs/root/flex/flex/skel.c,v 1.2 2004/05/07 00:28:17 jkh Exp $ + */ + #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 -#define YY_FLEX_SUBMINOR_VERSION 33 -#if YY_FLEX_SUBMINOR_VERSION > 0 -#define FLEX_BETA -#endif - -/* First, we deal with platform-specific or compiler-specific issues. */ -/* begin standard C headers. */ #include <stdio.h> -#include <string.h> -#include <errno.h> -#include <stdlib.h> - -/* end standard C headers. */ - -/* flex integer type definitions */ -#ifndef FLEXINT_H -#define FLEXINT_H -/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ - -#if __STDC_VERSION__ >= 199901L - -/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, - * if you want the limit (max/min) macros for int types. - */ -#ifndef __STDC_LIMIT_MACROS -#define __STDC_LIMIT_MACROS 1 -#endif - -#include <inttypes.h> -typedef int8_t flex_int8_t; -typedef uint8_t flex_uint8_t; -typedef int16_t flex_int16_t; -typedef uint16_t flex_uint16_t; -typedef int32_t flex_int32_t; -typedef uint32_t flex_uint32_t; -#else -typedef signed char flex_int8_t; -typedef short int flex_int16_t; -typedef int flex_int32_t; -typedef unsigned char flex_uint8_t; -typedef unsigned short int flex_uint16_t; -typedef unsigned int flex_uint32_t; -#endif /* ! C99 */ - -/* Limits of integral types. */ -#ifndef INT8_MIN -#define INT8_MIN (-128) -#endif -#ifndef INT16_MIN -#define INT16_MIN (-32767-1) -#endif -#ifndef INT32_MIN -#define INT32_MIN (-2147483647-1) -#endif -#ifndef INT8_MAX -#define INT8_MAX (127) -#endif -#ifndef INT16_MAX -#define INT16_MAX (32767) -#endif -#ifndef INT32_MAX -#define INT32_MAX (2147483647) -#endif -#ifndef UINT8_MAX -#define UINT8_MAX (255U) -#endif -#ifndef UINT16_MAX -#define UINT16_MAX (65535U) +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus #endif -#ifndef UINT32_MAX -#define UINT32_MAX (4294967295U) #endif -#endif /* ! FLEXINT_H */ #ifdef __cplusplus +#include <stdlib.h> +#include <unistd.h> + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST @@ -96,17 +34,34 @@ typedef unsigned int flex_uint32_t; #if __STDC__ +#define YY_USE_PROTOS #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include <io.h> +#include <stdlib.h> +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + /* Returned upon end-of-file. */ #define YY_NULL 0 @@ -121,75 +76,71 @@ typedef unsigned int flex_uint32_t; * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ -#define BEGIN (yy_start) = 1 + 2 * +#define BEGIN yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ -#define YY_START (((yy_start) - 1) / 2) +#define YY_START ((yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart(yyin ) +#define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ -#ifndef YY_BUF_SIZE #define YY_BUF_SIZE 16384 -#endif - -/* The state buf must be large enough to hold one state per character in the main buffer. - */ -#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) -#ifndef YY_TYPEDEF_YY_BUFFER_STATE -#define YY_TYPEDEF_YY_BUFFER_STATE typedef struct yy_buffer_state *YY_BUFFER_STATE; -#endif extern int yyleng; - extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 - #define YY_LESS_LINENO(n) - -/* Return all but the first "n" matched characters back to the input stream. */ +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - *yy_cp = (yy_hold_char); \ + *yy_cp = yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ - (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) -#define unput(c) yyunput( c, (yytext_ptr) ) +#define unput(c) yyunput( c, yytext_ptr ) /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ - -#ifndef YY_TYPEDEF_YY_SIZE_T -#define YY_TYPEDEF_YY_SIZE_T typedef unsigned int yy_size_t; -#endif -#ifndef YY_STRUCT_YY_BUFFER_STATE -#define YY_STRUCT_YY_BUFFER_STATE + struct yy_buffer_state { FILE *yy_input_file; @@ -226,16 +177,12 @@ struct yy_buffer_state */ int yy_at_bol; - int yy_bs_lineno; /**< The line count. */ - int yy_bs_column; /**< The column count. */ - /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; - #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process @@ -249,38 +196,28 @@ struct yy_buffer_state * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 - }; -#endif /* !YY_STRUCT_YY_BUFFER_STATE */ -/* Stack of input buffers. */ -static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */ -static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */ -static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */ +static YY_BUFFER_STATE yy_current_buffer = 0; /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". - * - * Returns the top of the stack, or NULL. */ -#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \ - ? (yy_buffer_stack)[(yy_buffer_stack_top)] \ - : NULL) +#define YY_CURRENT_BUFFER yy_current_buffer -/* Same as previous macro, but useful when we know that the buffer stack is not - * NULL or when we need an lvalue. For internal use only. - */ -#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)] /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; + static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; -static int yy_init = 0; /* whether we need to initialize */ +static int yy_init = 1; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches @@ -288,92 +225,66 @@ static int yy_start = 0; /* start state number */ */ static int yy_did_buffer_switch_on_eof; -void yyrestart (FILE *input_file ); -void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ); -YY_BUFFER_STATE yy_create_buffer (FILE *file,int size ); -void yy_delete_buffer (YY_BUFFER_STATE b ); -void yy_flush_buffer (YY_BUFFER_STATE b ); -void yypush_buffer_state (YY_BUFFER_STATE new_buffer ); -void yypop_buffer_state (void ); - -static void yyensure_buffer_stack (void ); -static void yy_load_buffer_state (void ); -static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file ); +void yyrestart YY_PROTO(( FILE *input_file )); -#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER ) +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) -YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size ); -YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str ); -YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len ); +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); -void *yyalloc (yy_size_t ); -void *yyrealloc (void *,yy_size_t ); -void yyfree (void * ); +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ - if ( ! YY_CURRENT_BUFFER ){ \ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer(yyin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ - if ( ! YY_CURRENT_BUFFER ){\ - yyensure_buffer_stack (); \ - YY_CURRENT_BUFFER_LVALUE = \ - yy_create_buffer(yyin,YY_BUF_SIZE ); \ - } \ - YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ } -#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) - -/* Begin user sect3 */ +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) typedef unsigned char YY_CHAR; - FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; - typedef int yy_state_type; - -extern int yylineno; - -int yylineno = 1; - extern char *yytext; #define yytext_ptr yytext -static yy_state_type yy_get_previous_state (void ); -static yy_state_type yy_try_NUL_trans (yy_state_type current_state ); -static int yy_get_next_buffer (void ); -static void yy_fatal_error (yyconst char msg[] ); +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ - (yytext_ptr) = yy_bp; \ - yyleng = (size_t) (yy_cp - yy_bp); \ - (yy_hold_char) = *yy_cp; \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ - (yy_c_buf_p) = yy_cp; + yy_c_buf_p = yy_cp; #define YY_NUM_RULES 16 #define YY_END_OF_BUFFER 17 -/* This struct is not used in this scanner, - but its presence is necessary. */ -struct yy_trans_info - { - flex_int32_t yy_verify; - flex_int32_t yy_nxt; - }; -static yyconst flex_int16_t yy_accept[46] = +static yyconst short int yy_accept[46] = { 0, 0, 0, 17, 15, 11, 12, 13, 10, 9, 14, 14, 14, 14, 10, 9, 14, 3, 14, 14, 1, @@ -382,7 +293,7 @@ static yyconst flex_int16_t yy_accept[46] = 14, 4, 14, 2, 0 } ; -static yyconst flex_int32_t yy_ec[256] = +static yyconst int yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -414,14 +325,14 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[23] = +static yyconst int yy_meta[23] = { 0, 1, 1, 2, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 } ; -static yyconst flex_int16_t yy_base[48] = +static yyconst short int yy_base[48] = { 0, 0, 0, 56, 57, 57, 57, 57, 0, 49, 0, 12, 13, 34, 0, 47, 0, 0, 40, 31, 0, @@ -430,7 +341,7 @@ static yyconst flex_int16_t yy_base[48] = 12, 0, 14, 0, 57, 34, 23 } ; -static yyconst flex_int16_t yy_def[48] = +static yyconst short int yy_def[48] = { 0, 45, 1, 45, 45, 45, 45, 45, 46, 47, 47, 47, 47, 47, 46, 47, 47, 47, 47, 47, 47, @@ -439,7 +350,7 @@ static yyconst flex_int16_t yy_def[48] = 47, 47, 47, 47, 0, 45, 45 } ; -static yyconst flex_int16_t yy_nxt[80] = +static yyconst short int yy_nxt[80] = { 0, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10, 11, 10, 12, 10, 10, 10, 13, 10, @@ -451,7 +362,7 @@ static yyconst flex_int16_t yy_nxt[80] = 45, 45, 45, 45, 45, 45, 45, 45, 45 } ; -static yyconst flex_int16_t yy_chk[80] = +static yyconst short int yy_chk[80] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -466,9 +377,6 @@ static yyconst flex_int16_t yy_chk[80] = static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; -extern int yy_flex_debug; -int yy_flex_debug = 0; - /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ @@ -477,8 +385,9 @@ int yy_flex_debug = 0; #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; -#line 1 "lex.l" -#line 2 "lex.l" +#line 1 "../../../lib/com_err/lex.l" +#define INITIAL 0 +#line 2 "../../../lib/com_err/lex.l" /* * Copyright (c) 1998 - 2000 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). @@ -533,23 +442,7 @@ static int getstring(void); #undef ECHO -#line 536 "lex.yy.c" - -#define INITIAL 0 - -#ifndef YY_NO_UNISTD_H -/* Special case for "unistd.h", since it is non-ANSI. We include it way - * down here because we want the user's section 1 to have been scanned first. - * The user has a chance to override it with an option. - */ -#include <unistd.h> -#endif - -#ifndef YY_EXTRA_TYPE -#define YY_EXTRA_TYPE void * -#endif - -static int yy_init_globals (void ); +#line 446 "lex.c" /* Macros after this point can all be overridden by user definitions in * section 1. @@ -557,30 +450,65 @@ static int yy_init_globals (void ); #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus -extern "C" int yywrap (void ); +extern "C" int yywrap YY_PROTO(( void )); #else -extern int yywrap (void ); +extern int yywrap YY_PROTO(( void )); #endif #endif - static void yyunput (int c,char *buf_ptr ); - +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + #ifndef yytext_ptr -static void yy_flex_strncpy (char *,yyconst char *,int ); +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * ); +static int yy_flex_strlen YY_PROTO(( yyconst char * )); #endif #ifndef YY_NO_INPUT - #ifdef __cplusplus -static int yyinput (void ); +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + #else -static int input (void ); +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 #endif +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include <stdlib.h> +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif #endif /* Amount of stuff to slurp up with each read. */ @@ -589,6 +517,7 @@ static int input (void ); #endif /* Copy whatever the last rule matched to the standard output. */ + #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). @@ -601,10 +530,9 @@ static int input (void ); */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ - if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + if ( yy_current_buffer->yy_is_interactive ) \ { \ - int c = '*'; \ - size_t n; \ + int c = '*', n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ @@ -614,22 +542,9 @@ static int input (void ); YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ - else \ - { \ - errno=0; \ - while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ - { \ - if( errno != EINTR) \ - { \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - break; \ - } \ - errno=0; \ - clearerr(yyin); \ - } \ - }\ -\ - + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - @@ -650,18 +565,12 @@ static int input (void ); #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif -/* end tables serialization structures and prototypes */ - /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL -#define YY_DECL_IS_OURS 1 - -extern int yylex (void); - -#define YY_DECL int yylex (void) -#endif /* !YY_DECL */ +#define YY_DECL int yylex YY_PROTO(( void )) +#endif /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. @@ -678,28 +587,26 @@ extern int yylex (void); #define YY_RULE_SETUP \ YY_USER_ACTION -/** The main scanner function which does all the work. - */ YY_DECL -{ + { register yy_state_type yy_current_state; register char *yy_cp, *yy_bp; register int yy_act; - -#line 59 "lex.l" -#line 691 "lex.yy.c" +#line 59 "../../../lib/com_err/lex.l" + +#line 599 "lex.c" - if ( !(yy_init) ) + if ( yy_init ) { - (yy_init) = 1; + yy_init = 0; #ifdef YY_USER_INIT YY_USER_INIT; #endif - if ( ! (yy_start) ) - (yy_start) = 1; /* first start state */ + if ( ! yy_start ) + yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; @@ -707,36 +614,34 @@ YY_DECL if ( ! yyout ) yyout = stdout; - if ( ! YY_CURRENT_BUFFER ) { - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer(yyin,YY_BUF_SIZE ); - } + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); - yy_load_buffer_state( ); + yy_load_buffer_state(); } while ( 1 ) /* loops until end-of-file is reached */ { - yy_cp = (yy_c_buf_p); + yy_cp = yy_c_buf_p; /* Support of yytext. */ - *yy_cp = (yy_hold_char); + *yy_cp = yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; - yy_current_state = (yy_start); + yy_current_state = yy_start; yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { @@ -753,132 +658,133 @@ yy_find_action: yy_act = yy_accept[yy_current_state]; if ( yy_act == 0 ) { /* have to back up */ - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; yy_act = yy_accept[yy_current_state]; } YY_DO_BEFORE_ACTION; + do_action: /* This label is used only to access EOF actions. */ + switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = (yy_hold_char); - yy_cp = (yy_last_accepting_cpos); - yy_current_state = (yy_last_accepting_state); + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; goto yy_find_action; case 1: YY_RULE_SETUP -#line 60 "lex.l" +#line 60 "../../../lib/com_err/lex.l" { return ET; } YY_BREAK case 2: YY_RULE_SETUP -#line 61 "lex.l" +#line 61 "../../../lib/com_err/lex.l" { return ET; } YY_BREAK case 3: YY_RULE_SETUP -#line 62 "lex.l" +#line 62 "../../../lib/com_err/lex.l" { return EC; } YY_BREAK case 4: YY_RULE_SETUP -#line 63 "lex.l" +#line 63 "../../../lib/com_err/lex.l" { return EC; } YY_BREAK case 5: YY_RULE_SETUP -#line 64 "lex.l" +#line 64 "../../../lib/com_err/lex.l" { return PREFIX; } YY_BREAK case 6: YY_RULE_SETUP -#line 65 "lex.l" +#line 65 "../../../lib/com_err/lex.l" { return INDEX; } YY_BREAK case 7: YY_RULE_SETUP -#line 66 "lex.l" +#line 66 "../../../lib/com_err/lex.l" { return ID; } YY_BREAK case 8: YY_RULE_SETUP -#line 67 "lex.l" +#line 67 "../../../lib/com_err/lex.l" { return END; } YY_BREAK case 9: YY_RULE_SETUP -#line 68 "lex.l" +#line 68 "../../../lib/com_err/lex.l" { yylval.number = atoi(yytext); return NUMBER; } YY_BREAK case 10: YY_RULE_SETUP -#line 69 "lex.l" +#line 69 "../../../lib/com_err/lex.l" ; YY_BREAK case 11: YY_RULE_SETUP -#line 70 "lex.l" +#line 70 "../../../lib/com_err/lex.l" ; YY_BREAK case 12: -/* rule 12 can match eol */ YY_RULE_SETUP -#line 71 "lex.l" +#line 71 "../../../lib/com_err/lex.l" { lineno++; } YY_BREAK case 13: YY_RULE_SETUP -#line 72 "lex.l" +#line 72 "../../../lib/com_err/lex.l" { return getstring(); } YY_BREAK case 14: YY_RULE_SETUP -#line 73 "lex.l" +#line 73 "../../../lib/com_err/lex.l" { yylval.string = strdup(yytext); return STRING; } YY_BREAK case 15: YY_RULE_SETUP -#line 74 "lex.l" +#line 74 "../../../lib/com_err/lex.l" { return *yytext; } YY_BREAK case 16: YY_RULE_SETUP -#line 75 "lex.l" +#line 75 "../../../lib/com_err/lex.l" ECHO; YY_BREAK -#line 855 "lex.yy.c" +#line 762 "lex.c" case YY_STATE_EOF(INITIAL): yyterminate(); case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1; + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = (yy_hold_char); + *yy_cp = yy_hold_char; YY_RESTORE_YY_MORE_OFFSET - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure - * consistency between YY_CURRENT_BUFFER and our + * consistency between yy_current_buffer and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position @@ -888,13 +794,13 @@ case YY_STATE_EOF(INITIAL): * end-of-buffer state). Contrast this with the test * in input(). */ - if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; - (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text; + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; - yy_current_state = yy_get_previous_state( ); + yy_current_state = yy_get_previous_state(); /* Okay, we're now positioned to make the NUL * transition. We couldn't have @@ -907,30 +813,30 @@ case YY_STATE_EOF(INITIAL): yy_next_state = yy_try_NUL_trans( yy_current_state ); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; + yy_bp = yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ - yy_cp = ++(yy_c_buf_p); + yy_cp = ++yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { - yy_cp = (yy_c_buf_p); + yy_cp = yy_c_buf_p; goto yy_find_action; } } - else switch ( yy_get_next_buffer( ) ) + else switch ( yy_get_next_buffer() ) { case EOB_ACT_END_OF_FILE: { - (yy_did_buffer_switch_on_eof) = 0; + yy_did_buffer_switch_on_eof = 0; - if ( yywrap( ) ) + if ( yywrap() ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up @@ -941,7 +847,7 @@ case YY_STATE_EOF(INITIAL): * YY_NULL, it'll still work - another * YY_NULL will get returned. */ - (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ; + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; @@ -949,30 +855,30 @@ case YY_STATE_EOF(INITIAL): else { - if ( ! (yy_did_buffer_switch_on_eof) ) + if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = - (yytext_ptr) + yy_amount_of_matched_text; + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; - yy_current_state = yy_get_previous_state( ); + yy_current_state = yy_get_previous_state(); - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: - (yy_c_buf_p) = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)]; + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; - yy_current_state = yy_get_previous_state( ); + yy_current_state = yy_get_previous_state(); - yy_cp = (yy_c_buf_p); - yy_bp = (yytext_ptr) + YY_MORE_ADJ; + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; @@ -983,7 +889,8 @@ case YY_STATE_EOF(INITIAL): "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ -} /* end of yylex */ + } /* end of yylex */ + /* yy_get_next_buffer - try to read in a new buffer * @@ -992,20 +899,21 @@ case YY_STATE_EOF(INITIAL): * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ -static int yy_get_next_buffer (void) -{ - register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; - register char *source = (yytext_ptr); + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; register int number_to_move, i; int ret_val; - if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] ) + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); - if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + if ( yy_current_buffer->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ - if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 ) + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. @@ -1025,30 +933,34 @@ static int yy_get_next_buffer (void) /* Try to read more data. */ /* First move last chars to start of buffer. */ - number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1; + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); - if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0; + yy_current_buffer->yy_n_chars = yy_n_chars = 0; else { - int num_to_read = - YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + YY_BUFFER_STATE b = yy_current_buffer; int yy_c_buf_p_offset = - (int) ((yy_c_buf_p) - b->yy_ch_buf); + (int) (yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { @@ -1061,7 +973,8 @@ static int yy_get_next_buffer (void) b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ - yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ); + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ @@ -1071,35 +984,35 @@ static int yy_get_next_buffer (void) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); - (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset]; + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; - num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; - +#endif } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ - YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), (size_t) num_to_read ); + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + yy_current_buffer->yy_n_chars = yy_n_chars; } - if ( (yy_n_chars) == 0 ) + if ( yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; - yyrestart(yyin ); + yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; - YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + yy_current_buffer->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } @@ -1107,31 +1020,32 @@ static int yy_get_next_buffer (void) else ret_val = EOB_ACT_CONTINUE_SCAN; - (yy_n_chars) += number_to_move; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR; - YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR; + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; - (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; return ret_val; -} + } + /* yy_get_previous_state - get the state just before the EOB char was reached */ - static yy_state_type yy_get_previous_state (void) -{ +static yy_state_type yy_get_previous_state() + { register yy_state_type yy_current_state; register char *yy_cp; - - yy_current_state = (yy_start); - for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp ) + yy_current_state = yy_start; + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { @@ -1143,23 +1057,30 @@ static int yy_get_next_buffer (void) } return yy_current_state; -} + } + /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ - static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state ) -{ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { register int yy_is_jam; - register char *yy_cp = (yy_c_buf_p); + register char *yy_cp = yy_c_buf_p; register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { - (yy_last_accepting_state) = yy_current_state; - (yy_last_accepting_cpos) = yy_cp; + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { @@ -1171,73 +1092,80 @@ static int yy_get_next_buffer (void) yy_is_jam = (yy_current_state == 45); return yy_is_jam ? 0 : yy_current_state; -} + } - static void yyunput (int c, register char * yy_bp ) -{ - register char *yy_cp; - - yy_cp = (yy_c_buf_p); + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; /* undo effects of setting up yytext */ - *yy_cp = (yy_hold_char); + *yy_cp = yy_hold_char; - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ - register int number_to_move = (yy_n_chars) + 2; - register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[ - YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2]; + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; register char *source = - &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]; + &yy_current_buffer->yy_ch_buf[number_to_move]; - while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + while ( source > yy_current_buffer->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size; + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; - if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 ) + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; - (yytext_ptr) = yy_bp; - (yy_hold_char) = *yy_cp; - (yy_c_buf_p) = yy_cp; -} -#ifndef YY_NO_INPUT + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + #ifdef __cplusplus - static int yyinput (void) +static int yyinput() #else - static int input (void) +static int input() #endif - -{ + { int c; - - *(yy_c_buf_p) = (yy_hold_char); - if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR ) + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ - if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] ) + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) /* This was really a NUL. */ - *(yy_c_buf_p) = '\0'; + *yy_c_buf_p = '\0'; else { /* need more input */ - int offset = (yy_c_buf_p) - (yytext_ptr); - ++(yy_c_buf_p); + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; - switch ( yy_get_next_buffer( ) ) + switch ( yy_get_next_buffer() ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() @@ -1251,16 +1179,16 @@ static int yy_get_next_buffer (void) */ /* Reset buffer status. */ - yyrestart(yyin ); + yyrestart( yyin ); - /*FALLTHROUGH*/ + /* fall through */ case EOB_ACT_END_OF_FILE: { - if ( yywrap( ) ) + if ( yywrap() ) return EOF; - if ( ! (yy_did_buffer_switch_on_eof) ) + if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); @@ -1270,92 +1198,90 @@ static int yy_get_next_buffer (void) } case EOB_ACT_CONTINUE_SCAN: - (yy_c_buf_p) = (yytext_ptr) + offset; + yy_c_buf_p = yytext_ptr + offset; break; } } } - c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */ - *(yy_c_buf_p) = '\0'; /* preserve yytext */ - (yy_hold_char) = *++(yy_c_buf_p); + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + return c; -} -#endif /* ifndef YY_NO_INPUT */ + } -/** Immediately switch to a different input stream. - * @param input_file A readable stream. - * - * @note This function does not reset the start condition to @c INITIAL . - */ - void yyrestart (FILE * input_file ) -{ - - if ( ! YY_CURRENT_BUFFER ){ - yyensure_buffer_stack (); - YY_CURRENT_BUFFER_LVALUE = - yy_create_buffer(yyin,YY_BUF_SIZE ); + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); } - yy_init_buffer(YY_CURRENT_BUFFER,input_file ); - yy_load_buffer_state( ); -} -/** Switch to a different input buffer. - * @param new_buffer The new input buffer. - * - */ - void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ) -{ - - /* TODO. We should be able to replace this entire function body - * with - * yypop_buffer_state(); - * yypush_buffer_state(new_buffer); - */ - yyensure_buffer_stack (); - if ( YY_CURRENT_BUFFER == new_buffer ) +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) return; - if ( YY_CURRENT_BUFFER ) + if ( yy_current_buffer ) { /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; } - YY_CURRENT_BUFFER_LVALUE = new_buffer; - yy_load_buffer_state( ); + yy_current_buffer = new_buffer; + yy_load_buffer_state(); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ - (yy_did_buffer_switch_on_eof) = 1; -} + yy_did_buffer_switch_on_eof = 1; + } -static void yy_load_buffer_state (void) -{ - (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; - (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; - yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; - (yy_hold_char) = *(yy_c_buf_p); -} -/** Allocate and initialize an input buffer state. - * @param file A readable stream. - * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. - * - * @return the allocated buffer state. - */ - YY_BUFFER_STATE yy_create_buffer (FILE * file, int size ) -{ +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); @@ -1364,75 +1290,80 @@ static void yy_load_buffer_state (void) /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ - b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 ); + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; - yy_init_buffer(b,file ); + yy_init_buffer( b, file ); return b; -} + } -/** Destroy the buffer. - * @param b a buffer created with yy_create_buffer() - * - */ - void yy_delete_buffer (YY_BUFFER_STATE b ) -{ - + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { if ( ! b ) return; - if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ - YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) - yyfree((void *) b->yy_ch_buf ); + yy_flex_free( (void *) b->yy_ch_buf ); - yyfree((void *) b ); -} + yy_flex_free( (void *) b ); + } -#ifndef __cplusplus -extern int isatty (int ); -#endif /* __cplusplus */ - -/* Initializes or reinitializes a buffer. - * This function is sometimes called more than once on the same buffer, - * such as during a yyrestart() or at EOF. - */ - static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file ) -{ - int oerrno = errno; - - yy_flush_buffer(b ); +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; - /* If b is the current buffer, then yy_init_buffer was _probably_ - * called from yyrestart() or through yy_get_next_buffer. - * In that case, we don't want to reset the lineno or column. - */ - if (b != YY_CURRENT_BUFFER){ - b->yy_bs_lineno = 1; - b->yy_bs_column = 0; - } +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; - - errno = oerrno; -} -/** Discard all buffered characters. On the next scan, YY_INPUT will be called. - * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. - * - */ - void yy_flush_buffer (YY_BUFFER_STATE b ) -{ - if ( ! b ) +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) return; b->yy_n_chars = 0; @@ -1449,121 +1380,29 @@ extern int isatty (int ); b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; - if ( b == YY_CURRENT_BUFFER ) - yy_load_buffer_state( ); -} - -/** Pushes the new state onto the stack. The new state becomes - * the current state. This function will allocate the stack - * if necessary. - * @param new_buffer The new state. - * - */ -void yypush_buffer_state (YY_BUFFER_STATE new_buffer ) -{ - if (new_buffer == NULL) - return; - - yyensure_buffer_stack(); - - /* This block is copied from yy_switch_to_buffer. */ - if ( YY_CURRENT_BUFFER ) - { - /* Flush out information for old buffer. */ - *(yy_c_buf_p) = (yy_hold_char); - YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p); - YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); - } - - /* Only push if top exists. Otherwise, replace top. */ - if (YY_CURRENT_BUFFER) - (yy_buffer_stack_top)++; - YY_CURRENT_BUFFER_LVALUE = new_buffer; - - /* copied from yy_switch_to_buffer. */ - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; -} - -/** Removes and deletes the top of the stack, if present. - * The next element becomes the new top. - * - */ -void yypop_buffer_state (void) -{ - if (!YY_CURRENT_BUFFER) - return; - - yy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - if ((yy_buffer_stack_top) > 0) - --(yy_buffer_stack_top); - - if (YY_CURRENT_BUFFER) { - yy_load_buffer_state( ); - (yy_did_buffer_switch_on_eof) = 1; - } -} - -/* Allocates the stack if it does not exist. - * Guarantees space for at least one push. - */ -static void yyensure_buffer_stack (void) -{ - int num_to_alloc; - - if (!(yy_buffer_stack)) { - - /* First allocation is just for 2 elements, since we don't know if this - * scanner will even need a stack. We use 2 instead of 1 to avoid an - * immediate realloc on the next call. - */ - num_to_alloc = 1; - (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc - (num_to_alloc * sizeof(struct yy_buffer_state*) - ); - - memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*)); - - (yy_buffer_stack_max) = num_to_alloc; - (yy_buffer_stack_top) = 0; - return; + if ( b == yy_current_buffer ) + yy_load_buffer_state(); } - if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){ - /* Increase the buffer to prepare for a possible push. */ - int grow_size = 8 /* arbitrary grow size */; - - num_to_alloc = (yy_buffer_stack_max) + grow_size; - (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc - ((yy_buffer_stack), - num_to_alloc * sizeof(struct yy_buffer_state*) - ); - - /* zero only the new slots.*/ - memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*)); - (yy_buffer_stack_max) = num_to_alloc; - } -} - -/** Setup the input buffer state to scan directly from a user-specified character buffer. - * @param base the character buffer - * @param size the size in bytes of the character buffer - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) -{ +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { YY_BUFFER_STATE b; - + if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; - b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) ); + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); @@ -1577,51 +1416,56 @@ YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size ) b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; - yy_switch_to_buffer(b ); + yy_switch_to_buffer( b ); return b; -} + } +#endif -/** Setup the input buffer state to scan a string. The next call to yylex() will - * scan from a @e copy of @a str. - * @param yystr a NUL-terminated string to scan - * - * @return the newly allocated buffer state object. - * @note If you want to scan bytes that may contain NUL values, then use - * yy_scan_bytes() instead. - */ -YY_BUFFER_STATE yy_scan_string (yyconst char * yystr ) -{ - - return yy_scan_bytes(yystr,strlen(yystr) ); -} -/** Setup the input buffer state to scan the given bytes. The next call to yylex() will - * scan from a @e copy of @a bytes. - * @param bytes the byte buffer to scan - * @param len the number of bytes in the buffer pointed to by @a bytes. - * - * @return the newly allocated buffer state object. - */ -YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) -{ +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; - + /* Get memory for full buffer, including space for trailing EOB's. */ - n = _yybytes_len + 2; - buf = (char *) yyalloc(n ); + n = len + 2; + buf = (char *) yy_flex_alloc( n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - for ( i = 0; i < _yybytes_len; ++i ) - buf[i] = yybytes[i]; + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; - buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; - b = yy_scan_buffer(buf,n ); + b = yy_scan_buffer( buf, n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); @@ -1631,196 +1475,148 @@ YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len ) b->yy_is_our_buffer = 1; return b; -} - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 + } #endif -static void yy_fatal_error (yyconst char* msg ) -{ - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); -} - -/* Redefine yyless() so it works in section 3 code. */ -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - int yyless_macro_arg = (n); \ - YY_LESS_LINENO(yyless_macro_arg);\ - yytext[yyleng] = (yy_hold_char); \ - (yy_c_buf_p) = yytext + yyless_macro_arg; \ - (yy_hold_char) = *(yy_c_buf_p); \ - *(yy_c_buf_p) = '\0'; \ - yyleng = yyless_macro_arg; \ - } \ - while ( 0 ) +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; -/* Accessor methods (get/set functions) to struct members. */ + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); -/** Get the current line number. - * - */ -int yyget_lineno (void) -{ - - return yylineno; -} + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); -/** Get the input stream. - * - */ -FILE *yyget_in (void) -{ - return yyin; -} + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); -/** Get the output stream. - * - */ -FILE *yyget_out (void) -{ - return yyout; -} + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } -/** Get the length of the current token. - * - */ -int yyget_leng (void) -{ - return yyleng; -} + yy_start_stack[yy_start_stack_ptr++] = YY_START; -/** Get the current token. - * - */ + BEGIN(new_state); + } +#endif -char *yyget_text (void) -{ - return yytext; -} -/** Set the current line number. - * @param line_number - * - */ -void yyset_lineno (int line_number ) -{ - - yylineno = line_number; -} +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); -/** Set the input stream. This does not discard the current - * input buffer. - * @param in_str A readable stream. - * - * @see yy_switch_to_buffer - */ -void yyset_in (FILE * in_str ) -{ - yyin = in_str ; -} + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif -void yyset_out (FILE * out_str ) -{ - yyout = out_str ; -} -int yyget_debug (void) -{ - return yy_flex_debug; -} +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif -void yyset_debug (int bdebug ) -{ - yy_flex_debug = bdebug ; -} +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif -static int yy_init_globals (void) -{ - /* Initialization is the same as for the non-reentrant scanner. - * This function is called from yylex_destroy(), so don't allocate here. - */ - - (yy_buffer_stack) = 0; - (yy_buffer_stack_top) = 0; - (yy_buffer_stack_max) = 0; - (yy_c_buf_p) = (char *) 0; - (yy_init) = 0; - (yy_start) = 0; - -/* Defined in main.c */ -#ifdef YY_STDINIT - yyin = stdin; - yyout = stdout; +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) #else - yyin = (FILE *) 0; - yyout = (FILE *) 0; +static void yy_fatal_error( msg ) +char msg[]; #endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } - /* For future reference: Set errno on error, since we are called by - * yylex_init() - */ - return 0; -} -/* yylex_destroy is for both reentrant and non-reentrant scanners. */ -int yylex_destroy (void) -{ - - /* Pop the buffer stack, destroying each element. */ - while(YY_CURRENT_BUFFER){ - yy_delete_buffer(YY_CURRENT_BUFFER ); - YY_CURRENT_BUFFER_LVALUE = NULL; - yypop_buffer_state(); - } - /* Destroy the stack itself. */ - yyfree((yy_buffer_stack) ); - (yy_buffer_stack) = NULL; +/* Redefine yyless() so it works in section 3 code. */ - /* Reset the globals. This is important in a non-reentrant scanner so the next time - * yylex() is called, initialization will occur. */ - yy_init_globals( ); +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) - return 0; -} -/* - * Internal utility routines. - */ +/* Internal utility routines. */ #ifndef yytext_ptr -static void yy_flex_strncpy (char* s1, yyconst char * s2, int n ) -{ +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; -} + } #endif #ifdef YY_NEED_STRLEN -static int yy_flex_strlen (yyconst char * s ) -{ +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { register int n; for ( n = 0; s[n]; ++n ) ; return n; -} + } #endif -void *yyalloc (yy_size_t size ) -{ + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { return (void *) malloc( size ); -} + } -void *yyrealloc (void * ptr, yy_size_t size ) -{ +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter @@ -1829,17 +1625,26 @@ void *yyrealloc (void * ptr, yy_size_t size ) * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); -} - -void yyfree (void * ptr ) -{ - free( (char *) ptr ); /* see yyrealloc() for (char *) cast */ -} - -#define YYTABLES_NAME "yytables" + } -#line 75 "lex.l" +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 75 "../../../lib/com_err/lex.l" #ifndef yywrap /* XXX */ @@ -1894,4 +1699,3 @@ error_message (const char *format, ...) va_end (args); numerror++; } - diff --git a/source4/heimdal/lib/com_err/parse.c b/source4/heimdal/lib/com_err/parse.c index e55dafa41e..a7160a4d42 100644 --- a/source4/heimdal/lib/com_err/parse.c +++ b/source4/heimdal/lib/com_err/parse.c @@ -1,82 +1,19 @@ -/* A Bison parser, made by GNU Bison 2.0. */ - -/* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ - -/* Written by Richard Stallman by simplifying the original so called - ``semantic'' parser. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -/* Identify Bison output. */ -#define YYBISON 1 - -/* Skeleton name. */ -#define YYSKELETON_NAME "yacc.c" - -/* Pure parsers. */ -#define YYPURE 0 - -/* Using locations. */ -#define YYLSP_NEEDED 0 - - - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - ET = 258, - INDEX = 259, - PREFIX = 260, - EC = 261, - ID = 262, - END = 263, - STRING = 264, - NUMBER = 265 - }; -#endif -#define ET 258 -#define INDEX 259 -#define PREFIX 260 -#define EC 261 -#define ID 262 -#define END 263 -#define STRING 264 -#define NUMBER 265 +/* A Bison parser, made from ../../../lib/com_err/parse.y + by GNU Bison version 1.28 */ +#define YYBISON 1 /* Identify Bison output. */ +#define ET 257 +#define INDEX 258 +#define PREFIX 259 +#define EC 260 +#define ID 261 +#define END 262 +#define STRING 263 +#define NUMBER 264 -/* Copy the first part of user declarations. */ -#line 1 "parse.y" +#line 1 "../../../lib/com_err/parse.y" /* * Copyright (c) 1998 - 2000 Kungliga Tekniska Högskolan @@ -128,748 +65,425 @@ extern char *yytext; #endif - -/* Enabling traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif - -/* Enabling verbose error messages. */ -#ifdef YYERROR_VERBOSE -# undef YYERROR_VERBOSE -# define YYERROR_VERBOSE 1 -#else -# define YYERROR_VERBOSE 0 -#endif - -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -#line 53 "parse.y" -typedef union YYSTYPE { +#line 53 "../../../lib/com_err/parse.y" +typedef union { char *string; int number; } YYSTYPE; -/* Line 190 of yacc.c. */ -#line 153 "$base.c" -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif - - - -/* Copy the second part of user declarations. */ - +#include <stdio.h> -/* Line 213 of yacc.c. */ -#line 165 "$base.c" +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif -#if ! defined (yyoverflow) || YYERROR_VERBOSE -# ifndef YYFREE -# define YYFREE free -# endif -# ifndef YYMALLOC -# define YYMALLOC malloc -# endif -/* The parser invokes alloca or malloc; define the necessary symbols. */ +#define YYFINAL 24 +#define YYFLAG -32768 +#define YYNTBASE 12 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 264 ? yytranslate[x] : 18) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 3, 4, 5, 6, + 7, 8, 9, 10 +}; -# ifdef YYSTACK_USE_ALLOCA -# if YYSTACK_USE_ALLOCA -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# else -# define YYSTACK_ALLOC alloca -# endif -# endif -# endif +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 1, 4, 7, 9, 12, 15, 19, 21, 24, + 27, 30, 32, 37 +}; -# ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# else -# if defined (__STDC__) || defined (__cplusplus) -# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif -# define YYSTACK_ALLOC YYMALLOC -# define YYSTACK_FREE YYFREE -# endif -#endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ +static const short yyrhs[] = { -1, + 13, 16, 0, 14, 15, 0, 15, 0, 7, 9, + 0, 3, 9, 0, 3, 9, 9, 0, 17, 0, + 16, 17, 0, 4, 10, 0, 5, 9, 0, 5, + 0, 6, 9, 11, 9, 0, 8, 0 +}; +#endif -#if (! defined (yyoverflow) \ - && (! defined (__cplusplus) \ - || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 64, 65, 68, 69, 72, 78, 84, 93, 94, 97, + 101, 109, 116, 136 +}; +#endif -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - short int yyss; - YYSTYPE yyvs; - }; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAXIMUM) - -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if defined (__GNUC__) && 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - register YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (0) -# endif -# endif - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack, Stack, yysize); \ - Stack = &yyptr->Stack; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (0) -#endif +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) -#if defined (__STDC__) || defined (__cplusplus) - typedef signed char yysigned_char; -#else - typedef short int yysigned_char; +static const char * const yytname[] = { "$","error","$undefined.","ET","INDEX", +"PREFIX","EC","ID","END","STRING","NUMBER","','","file","header","id","et","statements", +"statement", NULL +}; #endif -/* YYFINAL -- State number of the termination state. */ -#define YYFINAL 9 -/* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 23 - -/* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 12 -/* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 7 -/* YYNRULES -- Number of rules. */ -#define YYNRULES 15 -/* YYNRULES -- Number of states. */ -#define YYNSTATES 24 - -/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ -#define YYUNDEFTOK 2 -#define YYMAXUTOK 265 - -#define YYTRANSLATE(YYX) \ - ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) - -/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ -static const unsigned char yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 11, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, - 5, 6, 7, 8, 9, 10 +static const short yyr1[] = { 0, + 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, + 17, 17, 17, 17 }; -#if YYDEBUG -/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in - YYRHS. */ -static const unsigned char yyprhs[] = -{ - 0, 0, 3, 4, 7, 10, 12, 15, 18, 22, - 24, 27, 30, 33, 35, 40 +static const short yyr2[] = { 0, + 0, 2, 2, 1, 2, 2, 3, 1, 2, 2, + 2, 1, 4, 1 }; -/* YYRHS -- A `-1'-separated list of the rules' RHS. */ -static const yysigned_char yyrhs[] = -{ - 13, 0, -1, -1, 14, 17, -1, 15, 16, -1, - 16, -1, 7, 9, -1, 3, 9, -1, 3, 9, - 9, -1, 18, -1, 17, 18, -1, 4, 10, -1, - 5, 9, -1, 5, -1, 6, 9, 11, 9, -1, - 8, -1 +static const short yydefact[] = { 1, + 0, 0, 0, 0, 4, 6, 5, 0, 12, 0, + 14, 2, 8, 3, 7, 10, 11, 0, 9, 0, + 13, 0, 0, 0 }; -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const unsigned char yyrline[] = -{ - 0, 64, 64, 65, 68, 69, 72, 78, 84, 93, - 94, 97, 101, 109, 116, 136 +static const short yydefgoto[] = { 22, + 3, 4, 5, 12, 13 }; -#endif -#if YYDEBUG || YYERROR_VERBOSE -/* YYTNME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. - First, the terminals, then, starting at YYNTOKENS, nonterminals. */ -static const char *const yytname[] = -{ - "$end", "error", "$undefined", "ET", "INDEX", "PREFIX", "EC", "ID", - "END", "STRING", "NUMBER", "','", "$accept", "file", "header", "id", - "et", "statements", "statement", 0 +static const short yypact[] = { 0, + -3, -1, -4, 2,-32768, 1,-32768, 3, 5, 6, +-32768, -4,-32768,-32768,-32768,-32768,-32768, -2,-32768, 7, +-32768, 11, 12,-32768 }; -#endif -# ifdef YYPRINT -/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to - token YYLEX-NUM. */ -static const unsigned short int yytoknum[] = -{ - 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, - 265, 44 +static const short yypgoto[] = {-32768, +-32768,-32768, 13,-32768, 8 }; -# endif -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const unsigned char yyr1[] = -{ - 0, 12, 13, 13, 14, 14, 15, 16, 16, 17, - 17, 18, 18, 18, 18, 18 -}; -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const unsigned char yyr2[] = -{ - 0, 2, 0, 2, 2, 1, 2, 2, 3, 1, - 2, 2, 2, 1, 4, 1 -}; +#define YYLAST 20 -/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state - STATE-NUM when YYTABLE doesn't specify something else to do. Zero - means the default is an error. */ -static const unsigned char yydefact[] = -{ - 2, 0, 0, 0, 0, 0, 5, 7, 6, 1, - 0, 13, 0, 15, 3, 9, 4, 8, 11, 12, - 0, 10, 0, 14 -}; -/* YYDEFGOTO[NTERM-NUM]. */ -static const yysigned_char yydefgoto[] = -{ - -1, 3, 4, 5, 6, 14, 15 +static const short yytable[] = { 8, + 9, 10, 1, 11, 1, 6, 2, 7, 20, 15, + 23, 24, 16, 17, 18, 21, 14, 0, 0, 19 }; -/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing - STATE-NUM. */ -#define YYPACT_NINF -5 -static const yysigned_char yypact[] = -{ - 0, -3, -1, 5, -4, 6, -5, 1, -5, -5, - 2, 4, 7, -5, -4, -5, -5, -5, -5, -5, - 3, -5, 8, -5 +static const short yycheck[] = { 4, + 5, 6, 3, 8, 3, 9, 7, 9, 11, 9, + 0, 0, 10, 9, 9, 9, 4, -1, -1, 12 }; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/share/bison.simple" +/* This file comes from bison-1.28. */ -/* YYPGOTO[NTERM-NUM]. */ -static const yysigned_char yypgoto[] = -{ - -5, -5, -5, -5, 10, -5, 9 -}; +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. -/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If - positive, shift that token. If negative, reduce the rule which - number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, syntax error. */ -#define YYTABLE_NINF -1 -static const unsigned char yytable[] = -{ - 10, 11, 12, 1, 13, 9, 7, 2, 8, 1, - 17, 0, 18, 19, 22, 16, 20, 23, 0, 0, - 0, 0, 0, 21 -}; + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. -static const yysigned_char yycheck[] = -{ - 4, 5, 6, 3, 8, 0, 9, 7, 9, 3, - 9, -1, 10, 9, 11, 5, 9, 9, -1, -1, - -1, -1, -1, 14 -}; + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. -/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing - symbol of state STATE-NUM. */ -static const unsigned char yystos[] = -{ - 0, 3, 7, 13, 14, 15, 16, 9, 9, 0, - 4, 5, 6, 8, 17, 18, 16, 9, 10, 9, - 9, 18, 11, 9 -}; + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ -#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) -# define YYSIZE_T __SIZE_TYPE__ -#endif -#if ! defined (YYSIZE_T) && defined (size_t) -# define YYSIZE_T size_t +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +#ifndef YYSTACK_USE_ALLOCA +#ifdef alloca +#define YYSTACK_USE_ALLOCA +#else /* alloca not defined */ +#ifdef __GNUC__ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) +#define YYSTACK_USE_ALLOCA +#include <alloca.h> +#else /* not sparc */ +/* We think this test detects Watcom and Microsoft C. */ +/* This used to test MSDOS, but that is a bad idea + since that symbol is in the user namespace. */ +#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) +#if 0 /* No need for malloc.h, which pollutes the namespace; + instead, just don't use alloca. */ +#include <malloc.h> #endif -#if ! defined (YYSIZE_T) -# if defined (__STDC__) || defined (__cplusplus) -# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +/* I don't know what this was needed for, but it pollutes the namespace. + So I turned it off. rms, 2 May 1997. */ +/* #include <malloc.h> */ + #pragma alloca +#define YYSTACK_USE_ALLOCA +#else /* not MSDOS, or __TURBOC__, or _AIX */ +#if 0 +#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, + and on HPUX 10. Eventually we can turn this on. */ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#endif /* __hpux */ #endif -#if ! defined (YYSIZE_T) -# define YYSIZE_T unsigned int +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc */ +#endif /* not GNU C */ +#endif /* alloca not defined */ +#endif /* YYSTACK_USE_ALLOCA not defined */ + +#ifdef YYSTACK_USE_ALLOCA +#define YYSTACK_ALLOC alloca +#else +#define YYSTACK_ALLOC malloc #endif +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) -#define YYEMPTY (-2) +#define YYEMPTY -2 #define YYEOF 0 - #define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrorlab - - -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ - #define YYFAIL goto yyerrlab - #define YYRECOVERING() (!!yyerrstatus) - -#define YYBACKUP(Token, Value) \ +#define YYBACKUP(token, value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yytoken = YYTRANSLATE (yychar); \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ - { \ - yyerror ("syntax error: cannot back up");\ - YYERROR; \ - } \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ while (0) - #define YYTERROR 1 #define YYERRCODE 256 - -/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. - If N is 0, then set CURRENT to the empty location which ends - the previous symbol: RHS[0] (always defined). */ - -#define YYRHSLOC(Rhs, K) ((Rhs)[K]) -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - do \ - if (N) \ - { \ - (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ - (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ - (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ - (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ - } \ - else \ - { \ - (Current).first_line = (Current).last_line = \ - YYRHSLOC (Rhs, 0).last_line; \ - (Current).first_column = (Current).last_column = \ - YYRHSLOC (Rhs, 0).last_column; \ - } \ - while (0) -#endif - - -/* YY_LOCATION_PRINT -- Print the location on the stream. - This macro was not mandated originally: define only if we know - we won't break user code: when these are the locations we know. */ - -#ifndef YY_LOCATION_PRINT -# if YYLTYPE_IS_TRIVIAL -# define YY_LOCATION_PRINT(File, Loc) \ - fprintf (File, "%d.%d-%d.%d", \ - (Loc).first_line, (Loc).first_column, \ - (Loc).last_line, (Loc).last_column) -# else -# define YY_LOCATION_PRINT(File, Loc) ((void) 0) -# endif +#ifndef YYPURE +#define YYLEX yylex() #endif - -/* YYLEX -- calling `yylex' with the right arguments. */ - +#ifdef YYPURE +#ifdef YYLSP_NEEDED #ifdef YYLEX_PARAM -# define YYLEX yylex (YYLEX_PARAM) +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) #else -# define YYLEX yylex () +#define YYLEX yylex(&yylval, &yylloc) #endif - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) - -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ -do { \ - if (yydebug) \ - { \ - YYFPRINTF (stderr, "%s ", Title); \ - yysymprint (stderr, \ - Type, Value); \ - YYFPRINTF (stderr, "\n"); \ - } \ -} while (0) - -/*------------------------------------------------------------------. -| yy_stack_print -- Print the state stack from its BOTTOM up to its | -| TOP (included). | -`------------------------------------------------------------------*/ - -#if defined (__STDC__) || defined (__cplusplus) -static void -yy_stack_print (short int *bottom, short int *top) +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) #else -static void -yy_stack_print (bottom, top) - short int *bottom; - short int *top; +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ #endif -{ - YYFPRINTF (stderr, "Stack now"); - for (/* Nothing. */; bottom <= top; ++bottom) - YYFPRINTF (stderr, " %d", *bottom); - YYFPRINTF (stderr, "\n"); -} -# define YY_STACK_PRINT(Bottom, Top) \ -do { \ - if (yydebug) \ - yy_stack_print ((Bottom), (Top)); \ -} while (0) +/* If nonreentrant, generate the variables here */ +#ifndef YYPURE -/*------------------------------------------------. -| Report that the YYRULE is going to be reduced. | -`------------------------------------------------*/ +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ -#if defined (__STDC__) || defined (__cplusplus) -static void -yy_reduce_print (int yyrule) -#else -static void -yy_reduce_print (yyrule) - int yyrule; +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ #endif -{ - int yyi; - unsigned int yylno = yyrline[yyrule]; - YYFPRINTF (stderr, "Reducing stack by rule %d (line %u), ", - yyrule - 1, yylno); - /* Print the symbols being reduced, and their result. */ - for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) - YYFPRINTF (stderr, "%s ", yytname [yyrhs[yyi]]); - YYFPRINTF (stderr, "-> %s\n", yytname [yyr1[yyrule]]); -} -# define YY_REDUCE_PRINT(Rule) \ -do { \ - if (yydebug) \ - yy_reduce_print (Rule); \ -} while (0) +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ -int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -# define YY_SYMBOL_PRINT(Title, Type, Value, Location) -# define YY_STACK_PRINT(Bottom, Top) -# define YY_REDUCE_PRINT(Rule) -#endif /* !YYDEBUG */ +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif +/* YYINITDEPTH indicates the initial size of the parser's stacks */ -/* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH -# define YYINITDEPTH 200 +#define YYINITDEPTH 200 #endif -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ - Do not make this value too large; the results are undefined if - SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif #ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 +#define YYMAXDEPTH 10000 #endif - - -#if YYERROR_VERBOSE - -# ifndef yystrlen -# if defined (__GLIBC__) && defined (_STRING_H) -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -static YYSIZE_T -# if defined (__STDC__) || defined (__cplusplus) -yystrlen (const char *yystr) -# else -yystrlen (yystr) - const char *yystr; -# endif -{ - register const char *yys = yystr; - - while (*yys++ != '\0') - continue; - - return yys - yystr - 1; -} -# endif -# endif - -# ifndef yystpcpy -# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -# if defined (__STDC__) || defined (__cplusplus) -yystpcpy (char *yydest, const char *yysrc) -# else -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -# endif +/* Define __yy_memcpy. Note that the size argument + should be passed with type unsigned int, because that is what the non-GCC + definitions require. With GCC, __builtin_memcpy takes an arg + of type size_t, but it can handle unsigned int. */ + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (to, from, count) + char *to; + char *from; + unsigned int count; { - register char *yyd = yydest; - register const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; + register char *f = from; + register char *t = to; + register int i = count; - return yyd - 1; + while (i-- > 0) + *t++ = *f++; } -# endif -# endif - -#endif /* !YYERROR_VERBOSE */ - - -#if YYDEBUG -/*--------------------------------. -| Print this symbol on YYOUTPUT. | -`--------------------------------*/ +#else /* __cplusplus */ -#if defined (__STDC__) || defined (__cplusplus) -static void -yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) -#else +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ static void -yysymprint (yyoutput, yytype, yyvaluep) - FILE *yyoutput; - int yytype; - YYSTYPE *yyvaluep; -#endif +__yy_memcpy (char *to, char *from, unsigned int count) { - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; - - if (yytype < YYNTOKENS) - YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); - else - YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); - + register char *t = to; + register char *f = from; + register int i = count; -# ifdef YYPRINT - if (yytype < YYNTOKENS) - YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); -# endif - switch (yytype) - { - default: - break; - } - YYFPRINTF (yyoutput, ")"); + while (i-- > 0) + *t++ = *f++; } -#endif /* ! YYDEBUG */ -/*-----------------------------------------------. -| Release the memory associated to this symbol. | -`-----------------------------------------------*/ - -#if defined (__STDC__) || defined (__cplusplus) -static void -yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) -#else -static void -yydestruct (yymsg, yytype, yyvaluep) - const char *yymsg; - int yytype; - YYSTYPE *yyvaluep; #endif -{ - /* Pacify ``unused variable'' warnings. */ - (void) yyvaluep; - - if (!yymsg) - yymsg = "Deleting"; - YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); - - switch (yytype) - { - - default: - break; - } -} +#endif +#line 217 "/usr/share/bison.simple" -/* Prevent warnings from -Wmissing-prototypes. */ +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ #ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -int yyparse (void *YYPARSE_PARAM); -# else -int yyparse (); -# endif -#else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) -int yyparse (void); -#else -int yyparse (); -#endif -#endif /* ! YYPARSE_PARAM */ - - - -/* The look-ahead symbol. */ -int yychar; - -/* The semantic value of the look-ahead symbol. */ -YYSTYPE yylval; - -/* Number of syntax errors so far. */ -int yynerrs; - - - -/*----------. -| yyparse. | -`----------*/ - +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ #ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -int yyparse (void *YYPARSE_PARAM) -# else -int yyparse (YYPARSE_PARAM) - void *YYPARSE_PARAM; -# endif -#else /* ! YYPARSE_PARAM */ -#if defined (__STDC__) || defined (__cplusplus) -int -yyparse (void) +int yyparse (void *); #else -int -yyparse () - +int yyparse (void); #endif #endif + +int +yyparse(YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL { - register int yystate; register int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Look-ahead token as an internal (translated) token number. */ - int yytoken = 0; - - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. - - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - short int yyssa[YYINITDEPTH]; - short int *yyss = yyssa; - register short int *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; + register short *yyssp; register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else #define YYPOPSTACK (yyvsp--, yyssp--) +#endif - YYSIZE_T yystacksize = YYINITDEPTH; + int yystacksize = YYINITDEPTH; + int yyfree_stacks = 0; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ - /* When reducing, the number of symbols on the RHS of the reduced - rule. */ int yylen; - YYDPRINTF ((stderr, "Starting parse\n")); +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif yystate = 0; yyerrstatus = 0; @@ -881,254 +495,295 @@ yyparse () so that they stay on the same level as the state stack. The wasted elements are never initialized. */ - yyssp = yyss; + yyssp = yyss - 1; yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: - yyvsp[0] = yylval; - - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. - */ - yyssp++; - - yysetstate: - *yyssp = yystate; + *++yyssp = yystate; - if (yyss + yystacksize - 1 <= yyssp) + if (yyssp >= yyss + yystacksize - 1) { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; + int size = yyssp - yyss + 1; #ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - short int *yyss1 = yyss; - - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. This used to be a - conditional around just the two extra args, but that might - be undefined if yyoverflow is a macro. */ - yyoverflow ("parser stack overflow", - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - - &yystacksize); - - yyss = yyss1; - yyvs = yyvs1; - } + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif #else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyoverflowlab; -# else /* Extend the stack our own way. */ - if (YYMAXDEPTH <= yystacksize) - goto yyoverflowlab; + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 2; + } yystacksize *= 2; - if (YYMAXDEPTH < yystacksize) + if (yystacksize > YYMAXDEPTH) yystacksize = YYMAXDEPTH; - - { - short int *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyoverflowlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); - -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif +#ifndef YYSTACK_USE_ALLOCA + yyfree_stacks = 1; +#endif + yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, + size * (unsigned int) sizeof (*yyssp)); + yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, + size * (unsigned int) sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, + size * (unsigned int) sizeof (*yylsp)); +#endif #endif /* no yyoverflow */ - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; - + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif - if (yyss + yystacksize - 1 <= yyssp) + if (yyssp >= yyss + yystacksize - 1) YYABORT; } - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif goto yybackup; - -/*-----------. -| yybackup. | -`-----------*/ -yybackup: + yybackup: /* Do appropriate processing given the current state. */ -/* Read a look-ahead token if we need one and don't already have one. */ +/* Read a lookahead token if we need one and don't already have one. */ /* yyresume: */ - /* First try to decide what to do without reference to look-ahead token. */ + /* First try to decide what to do without reference to lookahead token. */ yyn = yypact[yystate]; - if (yyn == YYPACT_NINF) + if (yyn == YYFLAG) goto yydefault; - /* Not known => get a look-ahead token if don't already have one. */ + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ - /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { - YYDPRINTF ((stderr, "Reading a token: ")); +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif yychar = YYLEX; } - if (yychar <= YYEOF) + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ { - yychar = yytoken = YYEOF; - YYDPRINTF ((stderr, "Now at end of input.\n")); + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif } else { - yytoken = YYTRANSLATE (yychar); - YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif } - /* If the proper action on seeing token YYTOKEN is to reduce or to - detect an error, take that action. */ - yyn += yytoken; - if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) goto yydefault; + yyn = yytable[yyn]; - if (yyn <= 0) + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) { - if (yyn == 0 || yyn == YYTABLE_NINF) + if (yyn == YYFLAG) goto yyerrlab; yyn = -yyn; goto yyreduce; } + else if (yyn == 0) + goto yyerrlab; if (yyn == YYFINAL) YYACCEPT; - /* Shift the look-ahead token. */ - YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif - - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; - -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ +/* Do the default action for the current state. */ yydefault: + yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; - goto yyreduce; - -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ +/* Do a reduction. yyn is the number of a rule to reduce with. */ yyreduce: - /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets YYVAL to garbage. - This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - - - YY_REDUCE_PRINT (yyn); - switch (yyn) +#if YYDEBUG != 0 + if (yydebug) { - case 6: -#line 73 "parse.y" - { - id_str = (yyvsp[0].string); - } - break; + int i; - case 7: -#line 79 "parse.y" - { - base_id = name2number((yyvsp[0].string)); - strlcpy(name, (yyvsp[0].string), sizeof(name)); - free((yyvsp[0].string)); - } - break; + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); - case 8: -#line 85 "parse.y" - { - base_id = name2number((yyvsp[-1].string)); - strlcpy(name, (yyvsp[0].string), sizeof(name)); - free((yyvsp[-1].string)); - free((yyvsp[0].string)); - } - break; + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif - case 11: -#line 98 "parse.y" - { - number = (yyvsp[0].number); - } - break; - case 12: -#line 102 "parse.y" - { + switch (yyn) { + +case 5: +#line 73 "../../../lib/com_err/parse.y" +{ + id_str = yyvsp[0].string; + ; + break;} +case 6: +#line 79 "../../../lib/com_err/parse.y" +{ + base_id = name2number(yyvsp[0].string); + strlcpy(name, yyvsp[0].string, sizeof(name)); + free(yyvsp[0].string); + ; + break;} +case 7: +#line 85 "../../../lib/com_err/parse.y" +{ + base_id = name2number(yyvsp[-1].string); + strlcpy(name, yyvsp[0].string, sizeof(name)); + free(yyvsp[-1].string); + free(yyvsp[0].string); + ; + break;} +case 10: +#line 98 "../../../lib/com_err/parse.y" +{ + number = yyvsp[0].number; + ; + break;} +case 11: +#line 102 "../../../lib/com_err/parse.y" +{ free(prefix); - asprintf (&prefix, "%s_", (yyvsp[0].string)); + asprintf (&prefix, "%s_", yyvsp[0].string); if (prefix == NULL) errx(1, "malloc"); - free((yyvsp[0].string)); - } - break; - - case 13: -#line 110 "parse.y" - { + free(yyvsp[0].string); + ; + break;} +case 12: +#line 110 "../../../lib/com_err/parse.y" +{ prefix = realloc(prefix, 1); if (prefix == NULL) errx(1, "malloc"); *prefix = '\0'; - } - break; - - case 14: -#line 117 "parse.y" - { + ; + break;} +case 13: +#line 117 "../../../lib/com_err/parse.y" +{ struct error_code *ec = malloc(sizeof(*ec)); if (ec == NULL) @@ -1137,258 +792,246 @@ yyreduce: ec->next = NULL; ec->number = number; if(prefix && *prefix != '\0') { - asprintf (&ec->name, "%s%s", prefix, (yyvsp[-2].string)); + asprintf (&ec->name, "%s%s", prefix, yyvsp[-2].string); if (ec->name == NULL) errx(1, "malloc"); - free((yyvsp[-2].string)); + free(yyvsp[-2].string); } else - ec->name = (yyvsp[-2].string); - ec->string = (yyvsp[0].string); + ec->name = yyvsp[-2].string; + ec->string = yyvsp[0].string; APPEND(codes, ec); number++; - } - break; - - case 15: -#line 137 "parse.y" - { + ; + break;} +case 14: +#line 137 "../../../lib/com_err/parse.y" +{ YYACCEPT; - } - break; - - - } - -/* Line 1037 of yacc.c. */ -#line 1164 "$base.c" + ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 543 "/usr/share/bison.simple" yyvsp -= yylen; yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif - - YY_STACK_PRINT (yyss, yyssp); +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif *++yyvsp = yyval; +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ yyn = yyr1[yyn]; - yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; - if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else - yystate = yydefgoto[yyn - YYNTOKENS]; + yystate = yydefgoto[yyn - YYNTBASE]; goto yynewstate; +yyerrlab: /* here on detecting error */ -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ { ++yynerrs; -#if YYERROR_VERBOSE + +#ifdef YYERROR_VERBOSE yyn = yypact[yystate]; - if (YYPACT_NINF < yyn && yyn < YYLAST) + if (yyn > YYFLAG && yyn < YYLAST) { - YYSIZE_T yysize = 0; - int yytype = YYTRANSLATE (yychar); - const char* yyprefix; - char *yymsg; - int yyx; - - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - int yyxbegin = yyn < 0 ? -yyn : 0; - - /* Stay within bounds of both yycheck and yytname. */ - int yychecklim = YYLAST - yyn; - int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; - int yycount = 0; - - yyprefix = ", expecting "; - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) - { - yysize += yystrlen (yyprefix) + yystrlen (yytname [yyx]); - yycount += 1; - if (yycount == 5) - { - yysize = 0; - break; - } - } - yysize += (sizeof ("syntax error, unexpected ") - + yystrlen (yytname[yytype])); - yymsg = (char *) YYSTACK_ALLOC (yysize); - if (yymsg != 0) + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) { - char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); - yyp = yystpcpy (yyp, yytname[yytype]); + strcpy(msg, "parse error"); - if (yycount < 5) + if (count < 5) { - yyprefix = ", expecting "; - for (yyx = yyxbegin; yyx < yyxend; ++yyx) - if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) { - yyp = yystpcpy (yyp, yyprefix); - yyp = yystpcpy (yyp, yytname[yyx]); - yyprefix = " or "; + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; } } - yyerror (yymsg); - YYSTACK_FREE (yymsg); + yyerror(msg); + free(msg); } else - yyerror ("syntax error; also virtual memory exhausted"); + yyerror ("parse error; also virtual memory exceeded"); } else #endif /* YYERROR_VERBOSE */ - yyerror ("syntax error"); + yyerror("parse error"); } - + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ if (yyerrstatus == 3) { - /* If just tried and failed to reuse look-ahead token after an - error, discard it. */ - - if (yychar <= YYEOF) - { - /* If at end of input, pop the error token, - then the rest of the stack, then return failure. */ - if (yychar == YYEOF) - for (;;) - { - - YYPOPSTACK; - if (yyssp == yyss) - YYABORT; - yydestruct ("Error: popping", - yystos[*yyssp], yyvsp); - } - } - else - { - yydestruct ("Error: discarding", yytoken, &yylval); - yychar = YYEMPTY; - } + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; } - /* Else will try to reuse look-ahead token after shifting the error - token. */ - goto yyerrlab1; + /* Else will try to reuse lookahead token + after shifting the error token. */ + yyerrstatus = 3; /* Each real token shifted decrements this */ -/*---------------------------------------------------. -| yyerrorlab -- error raised explicitly by YYERROR. | -`---------------------------------------------------*/ -yyerrorlab: + goto yyerrhandle; -#ifdef __GNUC__ - /* Pacify GCC when the user code never invokes YYERROR and the label - yyerrorlab therefore never appears in user code. */ - if (0) - goto yyerrorlab; -#endif +yyerrdefault: /* current state does not do anything special for the error token. */ -yyvsp -= yylen; - yyssp -= yylen; - yystate = *yyssp; - goto yyerrlab1; +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif +yyerrpop: /* pop the current state because it cannot handle the error token */ -/*-------------------------------------------------------------. -| yyerrlab1 -- common code for both syntax error and YYERROR. | -`-------------------------------------------------------------*/ -yyerrlab1: - yyerrstatus = 3; /* Each real token shifted decrements this. */ + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif - for (;;) +#if YYDEBUG != 0 + if (yydebug) { - yyn = yypact[yystate]; - if (yyn != YYPACT_NINF) - { - yyn += YYTERROR; - if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) - { - yyn = yytable[yyn]; - if (0 < yyn) - break; - } - } + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif - /* Pop the current state because it cannot handle the error token. */ - if (yyssp == yyss) - YYABORT; +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; - yydestruct ("Error: popping", yystos[yystate], yyvsp); - YYPOPSTACK; - yystate = *yyssp; - YY_STACK_PRINT (yyss, yyssp); + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; } + else if (yyn == 0) + goto yyerrpop; if (yyn == YYFINAL) YYACCEPT; - *++yyvsp = yylval; - +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif - /* Shift the error token. */ - YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif yystate = yyn; goto yynewstate; - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yydestruct ("Error: discarding lookahead", - yytoken, &yylval); - yychar = YYEMPTY; - yyresult = 1; - goto yyreturn; - -#ifndef yyoverflow -/*----------------------------------------------. -| yyoverflowlab -- parser overflow comes here. | -`----------------------------------------------*/ -yyoverflowlab: - yyerror ("parser stack overflow"); - yyresult = 2; - /* Fall through. */ + yyacceptlab: + /* YYACCEPT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); #endif + } + return 0; -yyreturn: -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); + yyabortlab: + /* YYABORT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); #endif - return yyresult; + } + return 1; } - - -#line 142 "parse.y" +#line 142 "../../../lib/com_err/parse.y" static long @@ -1421,4 +1064,3 @@ yyerror (char *s) { error_message ("%s\n", s); } - diff --git a/source4/heimdal/lib/com_err/parse.h b/source4/heimdal/lib/com_err/parse.h index ef7b9ba91e..07e33790d3 100644 --- a/source4/heimdal/lib/com_err/parse.h +++ b/source4/heimdal/lib/com_err/parse.h @@ -1,70 +1,15 @@ -/* A Bison parser, made by GNU Bison 2.0. */ - -/* Skeleton parser for Yacc-like parsing with Bison, - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ - -/* Tokens. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - /* Put the tokens into the symbol table, so that GDB and other debuggers - know about them. */ - enum yytokentype { - ET = 258, - INDEX = 259, - PREFIX = 260, - EC = 261, - ID = 262, - END = 263, - STRING = 264, - NUMBER = 265 - }; -#endif -#define ET 258 -#define INDEX 259 -#define PREFIX 260 -#define EC 261 -#define ID 262 -#define END 263 -#define STRING 264 -#define NUMBER 265 - - - - -#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) -#line 53 "parse.y" -typedef union YYSTYPE { +typedef union { char *string; int number; } YYSTYPE; -/* Line 1318 of yacc.c. */ -#line 62 "parse.h" -# define yystype YYSTYPE /* obsolescent; will be withdrawn */ -# define YYSTYPE_IS_DECLARED 1 -# define YYSTYPE_IS_TRIVIAL 1 -#endif - -extern YYSTYPE yylval; - +#define ET 257 +#define INDEX 258 +#define PREFIX 259 +#define EC 260 +#define ID 261 +#define END 262 +#define STRING 263 +#define NUMBER 264 +extern YYSTYPE yylval; diff --git a/source4/heimdal/lib/des/evp.c b/source4/heimdal/lib/des/evp.c index fd6ac63ec2..34480dbe7e 100644 --- a/source4/heimdal/lib/des/evp.c +++ b/source4/heimdal/lib/des/evp.c @@ -17,14 +17,19 @@ #include <md4.h> #include <md5.h> +typedef int (*evp_md_init)(EVP_MD_CTX *); +typedef int (*evp_md_update)(EVP_MD_CTX *,const void *, size_t); +typedef int (*evp_md_final)(void *, EVP_MD_CTX *); +typedef int (*evp_md_cleanup)(EVP_MD_CTX *); + struct hc_evp_md { int hash_size; int block_size; int ctx_size; - int (*init)(EVP_MD_CTX *); - int (*update)(EVP_MD_CTX *,const void *, size_t ); - int (*final)(void *, EVP_MD_CTX *); - int (*cleanup)(EVP_MD_CTX *); + evp_md_init init; + evp_md_update update; + evp_md_final final; + evp_md_cleanup cleanup; }; /* @@ -151,19 +156,18 @@ EVP_Digest(const void *data, size_t dsize, void *hash, unsigned int *hsize, * */ -static const struct hc_evp_md sha256 = { - 32, - 64, - sizeof(SHA256_CTX), - (void *)SHA256_Init, - (void *)SHA256_Update, - (void *)SHA256_Final, - NULL -}; - const EVP_MD * EVP_sha256(void) { + static const struct hc_evp_md sha256 = { + 32, + 64, + sizeof(SHA256_CTX), + (evp_md_init)SHA256_Init, + (evp_md_update)SHA256_Update, + (evp_md_final)SHA256_Final, + NULL + }; return &sha256; } @@ -171,9 +175,9 @@ static const struct hc_evp_md sha1 = { 20, 64, sizeof(SHA_CTX), - (void *)SHA1_Init, - (void *)SHA1_Update, - (void *)SHA1_Final, + (evp_md_init)SHA1_Init, + (evp_md_update)SHA1_Update, + (evp_md_final)SHA1_Final, NULL }; @@ -196,9 +200,9 @@ EVP_md5(void) 16, 64, sizeof(MD5_CTX), - (void *)MD5_Init, - (void *)MD5_Update, - (void *)MD5_Final, + (evp_md_init)MD5_Init, + (evp_md_update)MD5_Update, + (evp_md_final)MD5_Final, NULL }; return &md5; @@ -211,9 +215,9 @@ EVP_md4(void) 16, 64, sizeof(MD4_CTX), - (void *)MD4_Init, - (void *)MD4_Update, - (void *)MD4_Final, + (evp_md_init)MD4_Init, + (evp_md_update)MD4_Update, + (evp_md_final)MD4_Final, NULL }; return &md4; @@ -226,9 +230,9 @@ EVP_md2(void) 16, 16, sizeof(MD2_CTX), - (void *)MD2_Init, - (void *)MD2_Update, - (void *)MD2_Final, + (evp_md_init)MD2_Init, + (evp_md_update)MD2_Update, + (evp_md_final)MD2_Final, NULL }; return &md2; @@ -258,9 +262,9 @@ EVP_md_null(void) 0, 0, 0, - (void *)null_Init, - (void *)null_Update, - (void *)null_Final, + (evp_md_init)null_Init, + (evp_md_update)null_Update, + (evp_md_final)null_Final, NULL }; return &null; @@ -878,3 +882,24 @@ EVP_BytesToKey(const EVP_CIPHER *type, return EVP_CIPHER_key_length(type); } +/* + * + */ + +void +OpenSSL_add_all_algorithms(void) +{ + return; +} + +void +OpenSSL_add_all_algorithms_conf(void) +{ + return; +} + +void +OpenSSL_add_all_algorithms_noconf(void) +{ + return; +} diff --git a/source4/heimdal/lib/des/evp.h b/source4/heimdal/lib/des/evp.h index 17d6d5fd41..2fdf8d0765 100644 --- a/source4/heimdal/lib/des/evp.h +++ b/source4/heimdal/lib/des/evp.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: evp.h,v 1.8 2006/04/21 15:00:54 lha Exp $ */ +/* $Id: evp.h,v 1.11 2006/10/07 17:21:24 lha Exp $ */ #ifndef HEIM_EVP_H #define HEIM_EVP_H 1 @@ -89,6 +89,9 @@ #define PKCS5_PBKDF2_HMAC_SHA1 hc_PKCS5_PBKDF2_HMAC_SHA1 #define EVP_BytesToKey hc_EVP_BytesToKey #define EVP_get_cipherbyname hc_EVP_get_cipherbyname +#define OpenSSL_add_all_algorithms hc_OpenSSL_add_all_algorithms +#define OpenSSL_add_all_algorithms_conf hc_OpenSSL_add_all_algorithms_conf +#define OpenSSL_add_all_algorithms_noconf hc_OpenSSL_add_all_algorithms_noconf /* * @@ -241,4 +244,12 @@ int EVP_BytesToKey(const EVP_CIPHER *, const EVP_MD *, unsigned int, void *, void *); +/* + * + */ + +void OpenSSL_add_all_algorithms(void); +void OpenSSL_add_all_algorithms_conf(void); +void OpenSSL_add_all_algorithms_noconf(void); + #endif /* HEIM_EVP_H */ diff --git a/source4/heimdal/lib/des/hmac.c b/source4/heimdal/lib/des/hmac.c index 4bcb0defa5..848b987a90 100644 --- a/source4/heimdal/lib/des/hmac.c +++ b/source4/heimdal/lib/des/hmac.c @@ -29,8 +29,8 @@ HMAC_CTX_cleanup(HMAC_CTX *ctx) ctx->ipad = NULL; } if (ctx->ctx) { - EVP_MD_CTX_destroy(ctx->ctx); - ctx->ctx = NULL; + EVP_MD_CTX_destroy(ctx->ctx); + ctx->ctx = NULL; } } diff --git a/source4/heimdal/lib/des/rand-unix.c b/source4/heimdal/lib/des/rand-unix.c new file mode 100644 index 0000000000..a51c6c0c0d --- /dev/null +++ b/source4/heimdal/lib/des/rand-unix.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +RCSID("$Id: rand-unix.c,v 1.2 2006/10/21 21:09:14 lha Exp $"); + +#include <stdio.h> +#include <stdlib.h> +#include <rand.h> + +#include <roken.h> + +/* + * Unix /dev/random + */ + +static int +get_device_fd(int flags) +{ + static const char *rnd_devices[] = { + "/dev/urandom", + "/dev/random", + "/dev/srandom", + "/dev/arandom", + NULL + }; + const char **p; + + for(p = rnd_devices; *p; p++) { + int fd = open(*p, flags | O_NDELAY); + if(fd >= 0) + return fd; + } + return -1; +} + +static void +unix_seed(const void *indata, int size) +{ + int fd; + + if (size <= 0) + return; + + fd = get_device_fd(O_WRONLY); + if (fd < 0) + return; + + write(fd, indata, size); + close(fd); + +} + +static int +unix_bytes(unsigned char *outdata, int size) +{ + ssize_t count; + int fd; + + if (size <= 0) + return 0; + + fd = get_device_fd(O_RDONLY); + if (fd < 0) + return 0; + + while (size > 0) { + count = read (fd, outdata, size); + if (count < 0 && errno == EINTR) + continue; + else if (count <= 0) { + close(fd); + return 0; + } + outdata += count; + size -= count; + } + close(fd); + + return 1; +} + +static void +unix_cleanup(void) +{ +} + +static void +unix_add(const void *indata, int size, double entropi) +{ + unix_seed(indata, size); +} + +static int +unix_pseudorand(unsigned char *outdata, int size) +{ + return unix_bytes(outdata, size); +} + +static int +unix_status(void) +{ + int fd; + + fd = get_device_fd(O_RDONLY); + if (fd < 0) + return 0; + close(fd); + + return 1; +} + +const RAND_METHOD hc_rand_unix_method = { + unix_seed, + unix_bytes, + unix_cleanup, + unix_add, + unix_pseudorand, + unix_status +}; diff --git a/source4/heimdal/lib/des/rand.c b/source4/heimdal/lib/des/rand.c new file mode 100644 index 0000000000..6eb959b724 --- /dev/null +++ b/source4/heimdal/lib/des/rand.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +RCSID("$Id: rand.c,v 1.7 2006/10/16 10:23:01 lha Exp $"); + +#include <stdio.h> +#include <stdlib.h> +#include <rand.h> + +#include <roken.h> + +extern RAND_METHOD hc_rand_unix_method; +static const RAND_METHOD *selected_meth = &hc_rand_unix_method; + +void +RAND_seed(const void *indata, size_t size) +{ + (*selected_meth->seed)(indata, size); +} + +int +RAND_bytes(void *outdata, size_t size) +{ + return (*selected_meth->bytes)(outdata, size); +} + +void +RAND_cleanup(void) +{ + (*selected_meth->cleanup)(); +} + +void +RAND_add(const void *indata, size_t size, double entropi) +{ + (*selected_meth->add)(indata, size, entropi); +} + +int +RAND_pseudo_bytes(void *outdata, size_t size) +{ + return (*selected_meth->pseudorand)(outdata, size); +} + +int +RAND_status(void) +{ + return (*selected_meth->status)(); +} + +int +RAND_set_rand_method(const RAND_METHOD *meth) +{ + selected_meth = meth; + return 1; +} + +const RAND_METHOD * +RAND_get_rand_method(void) +{ + return selected_meth; +} + +int +RAND_set_rand_engine(ENGINE *engine) +{ + return 1; +} + +int +RAND_load_file(const char *filename, size_t size) +{ + return 1; +} + +int +RAND_write_file(const char *filename) +{ + return 1; +} + +int +RAND_egd(const char *filename) +{ + return 1; +} diff --git a/source4/heimdal/lib/des/ui.c b/source4/heimdal/lib/des/ui.c index 276367e186..25b0ad293c 100644 --- a/source4/heimdal/lib/des/ui.c +++ b/source4/heimdal/lib/des/ui.c @@ -33,7 +33,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> -RCSID("$Id: ui.c,v 1.5 2006/01/08 21:47:29 lha Exp $"); +RCSID("$Id: ui.c,v 1.6 2006/09/22 15:45:57 lha Exp $"); #endif #include <stdio.h> @@ -53,11 +53,16 @@ intr(int sig) intr_flag++; } +#ifndef NSIG +#define NSIG 47 +#endif + static int read_string(const char *preprompt, const char *prompt, char *buf, size_t len, int echo) { - struct sigaction sigs[47]; + struct sigaction sigs[NSIG]; + int oksigs[NSIG]; struct sigaction sa; FILE *tty; int ret = 0; @@ -68,12 +73,16 @@ read_string(const char *preprompt, const char *prompt, struct termios t_new, t_old; + memset(&oksigs, 0, sizeof(oksigs)); + memset(&sa, 0, sizeof(sa)); sa.sa_handler = intr; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; - for(i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++) - if (i != SIGALRM) sigaction(i, &sa, &sigs[i]); + for(i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++) + if (i != SIGALRM) + if (sigaction(i, &sa, &sigs[i]) == 0) + oksigs[i] = 1; if((tty = fopen("/dev/tty", "r")) == NULL) tty = stdin; @@ -114,8 +123,9 @@ read_string(const char *preprompt, const char *prompt, if(tty != stdin) fclose(tty); - for(i = 0; i < sizeof(sigs) / sizeof(sigs[0]); i++) - if (i != SIGALRM) sigaction(i, &sigs[i], NULL); + for(i = 1; i < sizeof(sigs) / sizeof(sigs[0]); i++) + if (oksigs[i]) + sigaction(i, &sigs[i], NULL); if(ret) return -3; diff --git a/source4/heimdal/lib/gssapi/accept_sec_context.c b/source4/heimdal/lib/gssapi/accept_sec_context.c deleted file mode 100644 index 41a54bdab1..0000000000 --- a/source4/heimdal/lib/gssapi/accept_sec_context.c +++ /dev/null @@ -1,1176 +0,0 @@ -/* - * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "gssapi_locl.h" - -RCSID("$Id: accept_sec_context.c,v 1.55 2005/11/25 15:57:35 lha Exp $"); - -HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER; -krb5_keytab gssapi_krb5_keytab; - -OM_uint32 -gsskrb5_register_acceptor_identity (const char *identity) -{ - krb5_error_code ret; - - ret = gssapi_krb5_init(); - if(ret) - return GSS_S_FAILURE; - - HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); - - if(gssapi_krb5_keytab != NULL) { - krb5_kt_close(gssapi_krb5_context, gssapi_krb5_keytab); - gssapi_krb5_keytab = NULL; - } - if (identity == NULL) { - ret = krb5_kt_default(gssapi_krb5_context, &gssapi_krb5_keytab); - } else { - char *p; - - asprintf(&p, "FILE:%s", identity); - if(p == NULL) { - HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); - return GSS_S_FAILURE; - } - ret = krb5_kt_resolve(gssapi_krb5_context, p, &gssapi_krb5_keytab); - free(p); - } - HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); - if(ret) - return GSS_S_FAILURE; - return GSS_S_COMPLETE; -} - -void -gsskrb5_is_cfx(gss_ctx_id_t context_handle, int *is_cfx) -{ - krb5_keyblock *key; - int acceptor = (context_handle->more_flags & LOCAL) == 0; - *is_cfx = 0; - - if (acceptor) { - if (context_handle->auth_context->local_subkey) - key = context_handle->auth_context->local_subkey; - else - key = context_handle->auth_context->remote_subkey; - } else { - if (context_handle->auth_context->remote_subkey) - key = context_handle->auth_context->remote_subkey; - else - key = context_handle->auth_context->local_subkey; - } - if (key == NULL) - key = context_handle->auth_context->keyblock; - - if (key == NULL) - return; - - switch (key->keytype) { - case ETYPE_DES_CBC_CRC: - case ETYPE_DES_CBC_MD4: - case ETYPE_DES_CBC_MD5: - case ETYPE_DES3_CBC_MD5: - case ETYPE_DES3_CBC_SHA1: - case ETYPE_ARCFOUR_HMAC_MD5: - case ETYPE_ARCFOUR_HMAC_MD5_56: - break; - default : - *is_cfx = 1; - if ((acceptor && context_handle->auth_context->local_subkey) || - (!acceptor && context_handle->auth_context->remote_subkey)) - context_handle->more_flags |= ACCEPTOR_SUBKEY; - break; - } -} - - -static OM_uint32 -gsskrb5_accept_delegated_token - (OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - gss_cred_id_t * delegated_cred_handle) -{ - krb5_data *fwd_data = &(*context_handle)->fwd_data; - OM_uint32 *flags = &(*context_handle)->flags; - krb5_principal principal = (*context_handle)->source; - krb5_ccache ccache = NULL; - krb5_error_code kret; - int32_t ac_flags, ret = GSS_S_COMPLETE; - - *minor_status = 0; - - /* XXX Create a new delegated_cred_handle? */ - if (delegated_cred_handle == NULL) - kret = krb5_cc_default (gssapi_krb5_context, &ccache); - else - kret = krb5_cc_gen_new (gssapi_krb5_context, &krb5_mcc_ops, &ccache); - if (kret) { - *flags &= ~GSS_C_DELEG_FLAG; - goto out; - } - - kret = krb5_cc_initialize(gssapi_krb5_context, ccache, principal); - if (kret) { - *flags &= ~GSS_C_DELEG_FLAG; - goto out; - } - - krb5_auth_con_removeflags(gssapi_krb5_context, - (*context_handle)->auth_context, - KRB5_AUTH_CONTEXT_DO_TIME, - &ac_flags); - kret = krb5_rd_cred2(gssapi_krb5_context, - (*context_handle)->auth_context, - ccache, - fwd_data); - if (kret) - gssapi_krb5_set_error_string(); - krb5_auth_con_setflags(gssapi_krb5_context, - (*context_handle)->auth_context, - ac_flags); - if (kret) { - *flags &= ~GSS_C_DELEG_FLAG; - ret = GSS_S_FAILURE; - *minor_status = kret; - goto out; - } - - if (delegated_cred_handle) { - ret = gss_krb5_import_cred(minor_status, - ccache, - NULL, - NULL, - delegated_cred_handle); - if (ret != GSS_S_COMPLETE) - goto out; - - (*delegated_cred_handle)->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; - ccache = NULL; - } - -out: - if (ccache) { - if (delegated_cred_handle == NULL) - krb5_cc_close(gssapi_krb5_context, ccache); - else - krb5_cc_destroy(gssapi_krb5_context, ccache); - } - return ret; -} - -static OM_uint32 -gsskrb5_acceptor_ready( - OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - gss_cred_id_t * delegated_cred_handle) -{ - OM_uint32 ret; - int32_t seq_number; - int is_cfx = 0; - OM_uint32 *flags = &(*context_handle)->flags; - - krb5_auth_getremoteseqnumber (gssapi_krb5_context, - (*context_handle)->auth_context, - &seq_number); - - gsskrb5_is_cfx(*context_handle, &is_cfx); - - ret = _gssapi_msg_order_create(minor_status, - &(*context_handle)->order, - _gssapi_msg_order_f(*flags), - seq_number, 0, is_cfx); - if (ret) return ret; - - if (!(*flags & GSS_C_MUTUAL_FLAG) && _gssapi_msg_order_f(*flags)) { - krb5_auth_con_setlocalseqnumber(gssapi_krb5_context, - (*context_handle)->auth_context, - seq_number); - } - - /* - * We should handle the delegation ticket, in case it's there - */ - if ((*context_handle)->fwd_data.length > 0 && (*flags & GSS_C_DELEG_FLAG)) { - ret = gsskrb5_accept_delegated_token(minor_status, - context_handle, - delegated_cred_handle); - if (ret) return ret; - } else { - /* Well, looks like it wasn't there after all */ - *flags &= ~GSS_C_DELEG_FLAG; - } - - (*context_handle)->state = ACCEPTOR_READY; - (*context_handle)->more_flags |= OPEN; - - return GSS_S_COMPLETE; -} -static OM_uint32 -gsskrb5_acceptor_start - (OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - const gss_cred_id_t acceptor_cred_handle, - const gss_buffer_t input_token_buffer, - const gss_channel_bindings_t input_chan_bindings, - gss_name_t * src_name, - gss_OID * mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec, - gss_cred_id_t * delegated_cred_handle - ) -{ - krb5_error_code kret; - OM_uint32 ret = GSS_S_COMPLETE; - krb5_data indata; - krb5_flags ap_options; - OM_uint32 flags; - krb5_ticket *ticket = NULL; - krb5_keytab keytab = NULL; - krb5_keyblock *keyblock = NULL; - int is_cfx = 0; - - krb5_data_zero (&(*context_handle)->fwd_data); - - /* - * We may, or may not, have an escapsulation. - */ - ret = gssapi_krb5_decapsulate (minor_status, - input_token_buffer, - &indata, - "\x01\x00", - GSS_KRB5_MECHANISM); - - if (ret) { - /* No OID wrapping apparently available. */ - indata.length = input_token_buffer->length; - indata.data = input_token_buffer->value; - } - - /* - * We need to get our keytab - */ - if (acceptor_cred_handle == GSS_C_NO_CREDENTIAL) { - if (gssapi_krb5_keytab != NULL) { - keytab = gssapi_krb5_keytab; - } - } else if (acceptor_cred_handle->keytab != NULL) { - keytab = acceptor_cred_handle->keytab; - } - - /* - * We need to check the ticket and create the AP-REP packet - */ - kret = krb5_rd_req_return_keyblock(gssapi_krb5_context, - &(*context_handle)->auth_context, - &indata, - (acceptor_cred_handle == GSS_C_NO_CREDENTIAL) ? NULL : acceptor_cred_handle->principal, - keytab, - &ap_options, - &ticket, - &keyblock); - if (kret) { - ret = GSS_S_FAILURE; - *minor_status = kret; - gssapi_krb5_set_error_string (); - return ret; - } - - /* - * We need to remember some data on the context_handle - */ - (*context_handle)->ticket = ticket; - (*context_handle)->service_keyblock = keyblock; - (*context_handle)->lifetime = ticket->ticket.endtime; - - /* - * We need to copy the principal names to the context and the calling layer - */ - kret = krb5_copy_principal(gssapi_krb5_context, - ticket->client, - &(*context_handle)->source); - if (kret) { - ret = GSS_S_FAILURE; - *minor_status = kret; - gssapi_krb5_set_error_string (); - } - - kret = krb5_copy_principal (gssapi_krb5_context, - ticket->server, - &(*context_handle)->target); - if (kret) { - ret = GSS_S_FAILURE; - *minor_status = kret; - gssapi_krb5_set_error_string (); - return ret; - } - - /* - * We need to setup some compat stuff, this assumes that context_handle->target is already set - */ - ret = _gss_DES3_get_mic_compat(minor_status, *context_handle); - if (ret) { - return ret; - } - - if (src_name != NULL) { - kret = krb5_copy_principal (gssapi_krb5_context, - ticket->client, - src_name); - if (kret) { - ret = GSS_S_FAILURE; - *minor_status = kret; - gssapi_krb5_set_error_string (); - return ret; - } - } - - /* - * We need to get the flags out of the 8003 checksum - */ - { - krb5_authenticator authenticator; - - kret = krb5_auth_con_getauthenticator(gssapi_krb5_context, - (*context_handle)->auth_context, - &authenticator); - if(kret) { - ret = GSS_S_FAILURE; - *minor_status = kret; - gssapi_krb5_set_error_string (); - return ret; - } - - if (authenticator->cksum->cksumtype == CKSUMTYPE_GSSAPI) { - ret = gssapi_krb5_verify_8003_checksum(minor_status, - input_chan_bindings, - authenticator->cksum, - &flags, - &(*context_handle)->fwd_data); - - krb5_free_authenticator(gssapi_krb5_context, &authenticator); - if (ret) { - return ret; - } - } else { - krb5_crypto crypto; - - kret = krb5_crypto_init(gssapi_krb5_context, - (*context_handle)->auth_context->keyblock, - 0, &crypto); - if(kret) { - krb5_free_authenticator(gssapi_krb5_context, &authenticator); - - ret = GSS_S_FAILURE; - *minor_status = kret; - gssapi_krb5_set_error_string (); - return ret; - } - - /* Windows accepts Samba3's use of a kerberos, - rather than GSSAPI checksum here */ - kret = krb5_verify_checksum(gssapi_krb5_context, - crypto, KRB5_KU_AP_REQ_AUTH_CKSUM, NULL, 0, - authenticator->cksum); - krb5_free_authenticator(gssapi_krb5_context, &authenticator); - krb5_crypto_destroy(gssapi_krb5_context, crypto); - - if(kret) { - ret = GSS_S_BAD_SIG; - *minor_status = kret; - gssapi_krb5_set_error_string (); - return ret; - } - - flags = GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; - } - } - - if(flags & GSS_C_MUTUAL_FLAG) { - krb5_data outbuf; - - gsskrb5_is_cfx(*context_handle, &is_cfx); - - if (is_cfx != 0 - || (ap_options & AP_OPTS_USE_SUBKEY)) { - kret = krb5_auth_con_addflags(gssapi_krb5_context, - (*context_handle)->auth_context, - KRB5_AUTH_CONTEXT_USE_SUBKEY, - NULL); - (*context_handle)->more_flags |= ACCEPTOR_SUBKEY; - } - - kret = krb5_mk_rep(gssapi_krb5_context, - (*context_handle)->auth_context, - &outbuf); - if (kret) { - *minor_status = kret; - gssapi_krb5_set_error_string (); - return GSS_S_FAILURE; - } - - if (!(flags & GSS_C_DCE_STYLE)) { - ret = gssapi_krb5_encapsulate(minor_status, - &outbuf, - output_token, - "\x02\x00", - GSS_KRB5_MECHANISM); - krb5_data_free (&outbuf); - if (ret) { - return ret; - } - } else { - output_token->length = outbuf.length; - output_token->value = outbuf.data; - } - } - - flags |= GSS_C_TRANS_FLAG; - - /* Remember the flags */ - - (*context_handle)->lifetime = ticket->ticket.endtime; - (*context_handle)->flags = flags; - (*context_handle)->more_flags |= OPEN; - - if (mech_type) - *mech_type = GSS_KRB5_MECHANISM; - - if (time_rec) { - ret = gssapi_lifetime_left(minor_status, - (*context_handle)->lifetime, - time_rec); - if (ret) { - return ret; - } - } - - /* - * When GSS_C_DCE_STYLE is in use, we need ask for a AP-REP from the client - */ - if (flags & GSS_C_DCE_STYLE) { - if (ret_flags) { - /* Return flags to caller, but we haven't processed delgations yet */ - *ret_flags = flags & ~GSS_C_DELEG_FLAG; - } - - (*context_handle)->state = ACCEPTOR_WAIT_FOR_DCESTYLE; - return GSS_S_CONTINUE_NEEDED; - } - - ret = gsskrb5_acceptor_ready(minor_status, context_handle, delegated_cred_handle); - - /* - * We need to send the flags back to the caller - */ - - *ret_flags = (*context_handle)->flags; - return ret; -} - -static OM_uint32 -gsskrb5_acceptor_wait_for_dcestyle( - OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - const gss_cred_id_t acceptor_cred_handle, - const gss_buffer_t input_token_buffer, - const gss_channel_bindings_t input_chan_bindings, - gss_name_t * src_name, - gss_OID * mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec, - gss_cred_id_t * delegated_cred_handle) -{ - OM_uint32 ret; - krb5_error_code kret; - krb5_data inbuf; - OM_uint32 r_seq_number; - OM_uint32 l_seq_number; - - /* We know it's GSS_C_DCE_STYLE so we don't need to decapsulate the AP_REP */ - inbuf.length = input_token_buffer->length; - inbuf.data = input_token_buffer->value; - - /* - * We need to remeber the old remote seq_number, then check if the client has replied with our local seq_number, - * and then reset the remote seq_number to the old value - */ - { - kret = krb5_auth_con_getlocalseqnumber(gssapi_krb5_context, - (*context_handle)->auth_context, - &l_seq_number); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - kret = krb5_auth_getremoteseqnumber(gssapi_krb5_context, - (*context_handle)->auth_context, - &r_seq_number); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - kret = krb5_auth_con_setremoteseqnumber(gssapi_krb5_context, - (*context_handle)->auth_context, - l_seq_number); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - } - - /* We need to verify the AP_REP, but we need to flag that this - is DCE_STYLE, so don't check the timestamps this time - */ - { - krb5_ap_rep_enc_part *repl; - int32_t auth_flags; - - kret = krb5_auth_con_removeflags(gssapi_krb5_context, - (*context_handle)->auth_context, - KRB5_AUTH_CONTEXT_DO_TIME, &auth_flags); - if (kret) { /* Can't happen */ - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - kret = krb5_rd_rep(gssapi_krb5_context, - (*context_handle)->auth_context, - &inbuf, - &repl); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - /* Because the inbuf above is a final leg from client - * to server, we don't have a use for a 'reply' - * here */ - krb5_free_ap_rep_enc_part(gssapi_krb5_context, repl); - - /* Do no harm, put the flags back */ - kret = krb5_auth_con_setflags(gssapi_krb5_context, - (*context_handle)->auth_context, - auth_flags); - if (kret) { /* Can't happen */ - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - } - - /* We need to check the liftime */ - { - OM_uint32 lifetime_rec; - - ret = gssapi_lifetime_left(minor_status, - (*context_handle)->lifetime, - &lifetime_rec); - if (ret) { - return ret; - } - if (lifetime_rec == 0) { - return GSS_S_CONTEXT_EXPIRED; - } - - if (time_rec) *time_rec = lifetime_rec; - } - - /* We need to give the caller the flags which are in use */ - if (ret_flags) *ret_flags = (*context_handle)->flags; - - if (src_name) { - kret = krb5_copy_principal(gssapi_krb5_context, - (*context_handle)->source, - src_name); - if (kret) { - *minor_status = kret; - gssapi_krb5_set_error_string (); - return GSS_S_FAILURE; - } - } - - /* - * After the krb5_rd_rep() the remote and local seq_number should be the same, - * because the client just replies the seq_number from our AP-REP in its AP-REP, - * but then the client uses the seq_number from its AP-REQ for GSS_wrap() - */ - { - OM_uint32 tmp_r_seq_number; - OM_uint32 tmp_l_seq_number; - - kret = krb5_auth_getremoteseqnumber(gssapi_krb5_context, - (*context_handle)->auth_context, - &tmp_r_seq_number); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - kret = krb5_auth_con_getlocalseqnumber(gssapi_krb5_context, - (*context_handle)->auth_context, - &tmp_l_seq_number); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - /* - * Here we check if the client has responsed with our local seq_number, - */ - if (tmp_r_seq_number != tmp_l_seq_number) { - return GSS_S_UNSEQ_TOKEN; - } - } - - /* - * We need to reset the remote seq_number, because the client will use, - * the old one for the GSS_wrap() calls - */ - { - kret = krb5_auth_con_setremoteseqnumber(gssapi_krb5_context, - (*context_handle)->auth_context, - r_seq_number); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - } - - return gsskrb5_acceptor_ready(minor_status, context_handle, delegated_cred_handle); -} - -static OM_uint32 -gsskrb5_accept_sec_context - (OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - const gss_cred_id_t acceptor_cred_handle, - const gss_buffer_t input_token_buffer, - const gss_channel_bindings_t input_chan_bindings, - gss_name_t * src_name, - gss_OID * mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec, - gss_cred_id_t * delegated_cred_handle - ) -{ - OM_uint32 ret = GSS_S_COMPLETE; - krb5_data fwd_data; - gss_ctx_id_t local_context; - OM_uint32 minor_status2; - GSSAPI_KRB5_INIT(); - - krb5_data_zero (&fwd_data); - output_token->length = 0; - output_token->value = NULL; - - if (src_name != NULL) - *src_name = NULL; - if (mech_type) - *mech_type = GSS_KRB5_MECHANISM; - - if (*context_handle == GSS_C_NO_CONTEXT) { - ret = _gsskrb5_create_ctx(minor_status, - &local_context, - input_chan_bindings, - ACCEPTOR_START); - if (ret) return ret; - } else { - local_context = *context_handle; - } - - /* - * TODO: check the channel_bindings - * (above just sets them to krb5 layer) - */ - - HEIMDAL_MUTEX_lock(&(local_context)->ctx_id_mutex); - - switch ((local_context)->state) { - case ACCEPTOR_START: - ret = gsskrb5_acceptor_start(minor_status, - &local_context, - acceptor_cred_handle, - input_token_buffer, - input_chan_bindings, - src_name, - mech_type, - output_token, - ret_flags, - time_rec, - delegated_cred_handle); - break; - case ACCEPTOR_WAIT_FOR_DCESTYLE: - ret = gsskrb5_acceptor_wait_for_dcestyle(minor_status, - &local_context, - acceptor_cred_handle, - input_token_buffer, - input_chan_bindings, - src_name, - mech_type, - output_token, - ret_flags, - time_rec, - delegated_cred_handle); - break; - case ACCEPTOR_READY: - /* this function should not be called after it has returned GSS_S_COMPLETE */ - ret = GSS_S_BAD_STATUS; - break; - default: - /* TODO: is this correct here? --metze */ - ret = GSS_S_BAD_STATUS; - break; - } - - HEIMDAL_MUTEX_unlock(&(local_context)->ctx_id_mutex); - - if (*context_handle == GSS_C_NO_CONTEXT) { - if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { - *context_handle = local_context; - } else { - gss_delete_sec_context(&minor_status2, - &local_context, - NULL); - } - } - - return ret; -} - -static OM_uint32 -code_NegTokenArg(OM_uint32 *minor_status, - const NegTokenTarg *targ, - krb5_data *data, - u_char **ret_buf) -{ - OM_uint32 ret; - u_char *buf; - size_t buf_size, buf_len; - - buf_size = 1024; - buf = malloc(buf_size); - if (buf == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - do { - ret = encode_NegTokenTarg(buf + buf_size - 1, - buf_size, - targ, &buf_len); - if (ret == 0) { - size_t tmp; - - ret = der_put_length_and_tag(buf + buf_size - buf_len - 1, - buf_size - buf_len, - buf_len, - ASN1_C_CONTEXT, - CONS, - 1, - &tmp); - if (ret == 0) - buf_len += tmp; - } - if (ret) { - if (ret == ASN1_OVERFLOW) { - u_char *tmp; - - buf_size *= 2; - tmp = realloc (buf, buf_size); - if (tmp == NULL) { - *minor_status = ENOMEM; - free(buf); - return GSS_S_FAILURE; - } - buf = tmp; - } else { - *minor_status = ret; - free(buf); - return GSS_S_FAILURE; - } - } - } while (ret == ASN1_OVERFLOW); - - data->data = buf + buf_size - buf_len; - data->length = buf_len; - *ret_buf = buf; - return GSS_S_COMPLETE; -} - -static OM_uint32 -send_reject (OM_uint32 *minor_status, - gss_buffer_t output_token) -{ - NegTokenTarg targ; - krb5_data data; - u_char *buf; - OM_uint32 ret; - - ALLOC(targ.negResult, 1); - if (targ.negResult == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - *(targ.negResult) = reject; - targ.supportedMech = NULL; - targ.responseToken = NULL; - targ.mechListMIC = NULL; - - ret = code_NegTokenArg (minor_status, &targ, &data, &buf); - free_NegTokenTarg(&targ); - if (ret) - return ret; - -#if 0 - ret = _gssapi_encapsulate(minor_status, - &data, - output_token, - GSS_SPNEGO_MECHANISM); -#else - output_token->value = malloc(data.length); - if (output_token->value == NULL) { - *minor_status = ENOMEM; - ret = GSS_S_FAILURE; - } else { - output_token->length = data.length; - memcpy(output_token->value, data.data, output_token->length); - } -#endif - free(buf); - if (ret) - return ret; - return GSS_S_BAD_MECH; -} - -static OM_uint32 -send_accept (OM_uint32 *minor_status, - OM_uint32 major_status, - gss_buffer_t output_token, - gss_buffer_t mech_token, - gss_ctx_id_t context_handle, - const MechTypeList *mechtypelist) -{ - NegTokenTarg targ; - krb5_data data; - u_char *buf; - OM_uint32 ret; - gss_buffer_desc mech_buf, mech_mic_buf; - krb5_boolean require_mic; - - memset(&targ, 0, sizeof(targ)); - ALLOC(targ.negResult, 1); - if (targ.negResult == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - *(targ.negResult) = accept_completed; - - ALLOC(targ.supportedMech, 1); - if (targ.supportedMech == NULL) { - free_NegTokenTarg(&targ); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - ret = der_get_oid(GSS_KRB5_MECHANISM->elements, - GSS_KRB5_MECHANISM->length, - targ.supportedMech, - NULL); - if (ret) { - free_NegTokenTarg(&targ); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - if (mech_token != NULL && mech_token->length != 0) { - ALLOC(targ.responseToken, 1); - if (targ.responseToken == NULL) { - free_NegTokenTarg(&targ); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - targ.responseToken->length = mech_token->length; - targ.responseToken->data = mech_token->value; - mech_token->length = 0; - mech_token->value = NULL; - } else { - targ.responseToken = NULL; - } - - ret = _gss_spnego_require_mechlist_mic(minor_status, context_handle, - &require_mic); - if (ret) { - free_NegTokenTarg(&targ); - return ret; - } - - if (major_status == GSS_S_COMPLETE && require_mic) { - size_t buf_len; - - ALLOC(targ.mechListMIC, 1); - if (targ.mechListMIC == NULL) { - free_NegTokenTarg(&targ); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - ASN1_MALLOC_ENCODE(MechTypeList, mech_buf.value, mech_buf.length, - mechtypelist, &buf_len, ret); - if (ret) { - free_NegTokenTarg(&targ); - return ret; - } - if (mech_buf.length != buf_len) - abort(); - - ret = gss_get_mic(minor_status, context_handle, 0, &mech_buf, - &mech_mic_buf); - free (mech_buf.value); - if (ret) { - free_NegTokenTarg(&targ); - return ret; - } - - targ.mechListMIC->length = mech_mic_buf.length; - targ.mechListMIC->data = mech_mic_buf.value; - } else - targ.mechListMIC = NULL; - - ret = code_NegTokenArg (minor_status, &targ, &data, &buf); - free_NegTokenTarg(&targ); - if (ret) - return ret; - -#if 0 - ret = _gssapi_encapsulate(minor_status, - &data, - output_token, - GSS_SPNEGO_MECHANISM); -#else - output_token->value = malloc(data.length); - if (output_token->value == NULL) { - *minor_status = ENOMEM; - ret = GSS_S_FAILURE; - } else { - output_token->length = data.length; - memcpy(output_token->value, data.data, output_token->length); - } -#endif - free(buf); - if (ret) - return ret; - return GSS_S_COMPLETE; -} - -static OM_uint32 -spnego_accept_sec_context - (OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - const gss_cred_id_t acceptor_cred_handle, - const gss_buffer_t input_token_buffer, - const gss_channel_bindings_t input_chan_bindings, - gss_name_t * src_name, - gss_OID * mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec, - gss_cred_id_t * delegated_cred_handle - ) -{ - OM_uint32 ret, ret2; - NegTokenInit ni; - size_t ni_len; - int i; - int found = 0; - krb5_data data; - size_t len, taglen; - - output_token->length = 0; - output_token->value = NULL; - - ret = _gssapi_decapsulate (minor_status, - input_token_buffer, - &data, - GSS_SPNEGO_MECHANISM); - if (ret) - return ret; - - ret = der_match_tag_and_length(data.data, data.length, - ASN1_C_CONTEXT, CONS, 0, &len, &taglen); - if (ret) - return ret; - - if(len > data.length - taglen) - return ASN1_OVERRUN; - - ret = decode_NegTokenInit((const unsigned char *)data.data + taglen, len, - &ni, &ni_len); - if (ret) - return GSS_S_DEFECTIVE_TOKEN; - - if (ni.mechTypes == NULL) { - free_NegTokenInit(&ni); - return send_reject (minor_status, output_token); - } - - for (i = 0; !found && i < ni.mechTypes->len; ++i) { - unsigned char mechbuf[17]; - size_t mech_len; - - ret = der_put_oid (mechbuf + sizeof(mechbuf) - 1, - sizeof(mechbuf), - &ni.mechTypes->val[i], - &mech_len); - if (ret) { - free_NegTokenInit(&ni); - return GSS_S_DEFECTIVE_TOKEN; - } - if (mech_len == GSS_KRB5_MECHANISM->length - && memcmp(GSS_KRB5_MECHANISM->elements, - mechbuf + sizeof(mechbuf) - mech_len, - mech_len) == 0) - found = 1; - } - if (found) { - gss_buffer_desc ibuf, obuf; - gss_buffer_t ot = NULL; - OM_uint32 minor; - - if (ni.mechToken != NULL) { - ibuf.length = ni.mechToken->length; - ibuf.value = ni.mechToken->data; - - ret = gsskrb5_accept_sec_context(&minor, - context_handle, - acceptor_cred_handle, - &ibuf, - input_chan_bindings, - src_name, - mech_type, - &obuf, - ret_flags, - time_rec, - delegated_cred_handle); - if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { - ot = &obuf; - } else { - free_NegTokenInit(&ni); - send_reject (minor_status, output_token); - return ret; - } - } - ret2 = send_accept (minor_status, ret, output_token, ot, - *context_handle, ni.mechTypes); - if (ret2 != GSS_S_COMPLETE) - ret = ret2; - if (ot != NULL) - gss_release_buffer(&minor, ot); - free_NegTokenInit(&ni); - return ret; - } else { - free_NegTokenInit(&ni); - return send_reject (minor_status, output_token); - } -} - -OM_uint32 -gss_accept_sec_context - (OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - const gss_cred_id_t acceptor_cred_handle, - const gss_buffer_t input_token_buffer, - const gss_channel_bindings_t input_chan_bindings, - gss_name_t * src_name, - gss_OID * mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec, - gss_cred_id_t * delegated_cred_handle - ) -{ - OM_uint32 ret; - ssize_t mech_len; - const u_char *p; - - *minor_status = 0; - - mech_len = gssapi_krb5_get_mech (input_token_buffer->value, - input_token_buffer->length, - &p); - - /* This could be 'dce style' kerberos, where the OID is missing :-( */ - if ((mech_len < 0) || ((mech_len == GSS_KRB5_MECHANISM->length) - && memcmp(p, GSS_KRB5_MECHANISM->elements, mech_len) == 0)) - ret = gsskrb5_accept_sec_context(minor_status, - context_handle, - acceptor_cred_handle, - input_token_buffer, - input_chan_bindings, - src_name, - mech_type, - output_token, - ret_flags, - time_rec, - delegated_cred_handle); - else if (mech_len == GSS_SPNEGO_MECHANISM->length - && memcmp(p, GSS_SPNEGO_MECHANISM->elements, mech_len) == 0) - ret = spnego_accept_sec_context(minor_status, - context_handle, - acceptor_cred_handle, - input_token_buffer, - input_chan_bindings, - src_name, - mech_type, - output_token, - ret_flags, - time_rec, - delegated_cred_handle); - else - return GSS_S_BAD_MECH; - - return ret; -} diff --git a/source4/heimdal/lib/gssapi/gssapi.h b/source4/heimdal/lib/gssapi/gssapi.h index eac2737f43..340b35377d 100644 --- a/source4/heimdal/lib/gssapi/gssapi.h +++ b/source4/heimdal/lib/gssapi/gssapi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * Copyright (c) 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,802 +31,11 @@ * SUCH DAMAGE. */ -/* $Id: gssapi.h,v 1.40 2006/05/05 11:08:29 lha Exp $ */ +/* $Id: gssapi.h,v 1.50 2006/10/07 20:57:15 lha Exp $ */ #ifndef GSSAPI_H_ #define GSSAPI_H_ -/* - * First, include stddef.h to get size_t defined. - */ -#include <stddef.h> - -#include <krb5-types.h> - -/* - * Now define the three implementation-dependent types. - */ - -typedef uint32_t OM_uint32; - -typedef uint32_t gss_uint32; - -/* - * This is to avoid having to include <krb5.h> - */ - -struct krb5_auth_context_data; - -struct Principal; - -/* typedef void *gss_name_t; */ - -typedef struct Principal *gss_name_t; - -struct gss_ctx_id_t_desc_struct; -typedef struct gss_ctx_id_t_desc_struct *gss_ctx_id_t; - -typedef struct gss_OID_desc_struct { - OM_uint32 length; - void *elements; -} gss_OID_desc, *gss_OID; - -typedef struct gss_OID_set_desc_struct { - size_t count; - gss_OID elements; -} gss_OID_set_desc, *gss_OID_set; - -struct krb5_keytab_data; - -struct krb5_ccache_data; - -typedef int gss_cred_usage_t; - -struct gss_cred_id_t_desc_struct; -typedef struct gss_cred_id_t_desc_struct *gss_cred_id_t; - -typedef struct gss_buffer_desc_struct { - size_t length; - void *value; -} gss_buffer_desc, *gss_buffer_t; - -typedef struct gss_channel_bindings_struct { - OM_uint32 initiator_addrtype; - gss_buffer_desc initiator_address; - OM_uint32 acceptor_addrtype; - gss_buffer_desc acceptor_address; - gss_buffer_desc application_data; -} *gss_channel_bindings_t; - -/* - * For now, define a QOP-type as an OM_uint32 - */ -typedef OM_uint32 gss_qop_t; - -/* - * Flag bits for context-level services. - */ -#define GSS_C_DELEG_FLAG 1 /* 0x00000001 */ -#define GSS_C_MUTUAL_FLAG 2 /* 0x00000002 */ -#define GSS_C_REPLAY_FLAG 4 /* 0x00000004 */ -#define GSS_C_SEQUENCE_FLAG 8 /* 0x00000008 */ -#define GSS_C_CONF_FLAG 16 /* 0x00000010 */ -#define GSS_C_INTEG_FLAG 32 /* 0x00000020 */ -#define GSS_C_ANON_FLAG 64 /* 0x00000040 */ -#define GSS_C_PROT_READY_FLAG 128 /* 0x00000080 */ -#define GSS_C_TRANS_FLAG 256 /* 0x00000100 */ - -/* these are from draft-brezak-win2k-krb-rc4-hmac-04.txt */ -#define GSS_C_DCE_STYLE 4096 /* 0x00001000 */ -#define GSS_C_IDENTIFY_FLAG 8192 /* 0x00002000 */ -#define GSS_C_EXTENDED_ERROR_FLAG 16384 /* 0x00004000 */ - -/* - * Credential usage options - */ -#define GSS_C_BOTH 0 -#define GSS_C_INITIATE 1 -#define GSS_C_ACCEPT 2 - -/* - * Status code types for gss_display_status - */ -#define GSS_C_GSS_CODE 1 -#define GSS_C_MECH_CODE 2 - -/* - * The constant definitions for channel-bindings address families - */ -#define GSS_C_AF_UNSPEC 0 -#define GSS_C_AF_LOCAL 1 -#define GSS_C_AF_INET 2 -#define GSS_C_AF_IMPLINK 3 -#define GSS_C_AF_PUP 4 -#define GSS_C_AF_CHAOS 5 -#define GSS_C_AF_NS 6 -#define GSS_C_AF_NBS 7 -#define GSS_C_AF_ECMA 8 -#define GSS_C_AF_DATAKIT 9 -#define GSS_C_AF_CCITT 10 -#define GSS_C_AF_SNA 11 -#define GSS_C_AF_DECnet 12 -#define GSS_C_AF_DLI 13 -#define GSS_C_AF_LAT 14 -#define GSS_C_AF_HYLINK 15 -#define GSS_C_AF_APPLETALK 16 -#define GSS_C_AF_BSC 17 -#define GSS_C_AF_DSS 18 -#define GSS_C_AF_OSI 19 -#define GSS_C_AF_X25 21 -#define GSS_C_AF_INET6 24 - -#define GSS_C_AF_NULLADDR 255 - -/* - * Various Null values - */ -#define GSS_C_NO_NAME ((gss_name_t) 0) -#define GSS_C_NO_BUFFER ((gss_buffer_t) 0) -#define GSS_C_NO_OID ((gss_OID) 0) -#define GSS_C_NO_OID_SET ((gss_OID_set) 0) -#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0) -#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0) -#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0) -#define GSS_C_EMPTY_BUFFER {0, NULL} - -/* - * Some alternate names for a couple of the above - * values. These are defined for V1 compatibility. - */ -#define GSS_C_NULL_OID GSS_C_NO_OID -#define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET - -/* - * Define the default Quality of Protection for per-message - * services. Note that an implementation that offers multiple - * levels of QOP may define GSS_C_QOP_DEFAULT to be either zero - * (as done here) to mean "default protection", or to a specific - * explicit QOP value. However, a value of 0 should always be - * interpreted by a GSSAPI implementation as a request for the - * default protection level. - */ -#define GSS_C_QOP_DEFAULT 0 - -#define GSS_KRB5_CONF_C_QOP_DES 0x0100 -#define GSS_KRB5_CONF_C_QOP_DES3_KD 0x0200 - -/* - * Expiration time of 2^32-1 seconds means infinite lifetime for a - * credential or security context - */ -#define GSS_C_INDEFINITE 0xfffffffful - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * The implementation must reserve static storage for a - * gss_OID_desc object containing the value - * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" - * "\x01\x02\x01\x01"}, - * corresponding to an object-identifier value of - * {iso(1) member-body(2) United States(840) mit(113554) - * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant - * GSS_C_NT_USER_NAME should be initialized to point - * to that gss_OID_desc. - */ -extern gss_OID GSS_C_NT_USER_NAME; - -/* - * The implementation must reserve static storage for a - * gss_OID_desc object containing the value - * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" - * "\x01\x02\x01\x02"}, - * corresponding to an object-identifier value of - * {iso(1) member-body(2) United States(840) mit(113554) - * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. - * The constant GSS_C_NT_MACHINE_UID_NAME should be - * initialized to point to that gss_OID_desc. - */ -extern gss_OID GSS_C_NT_MACHINE_UID_NAME; - -/* - * The implementation must reserve static storage for a - * gss_OID_desc object containing the value - * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" - * "\x01\x02\x01\x03"}, - * corresponding to an object-identifier value of - * {iso(1) member-body(2) United States(840) mit(113554) - * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. - * The constant GSS_C_NT_STRING_UID_NAME should be - * initialized to point to that gss_OID_desc. - */ -extern gss_OID GSS_C_NT_STRING_UID_NAME; - -/* - * The implementation must reserve static storage for a - * gss_OID_desc object containing the value - * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, - * corresponding to an object-identifier value of - * {iso(1) org(3) dod(6) internet(1) security(5) - * nametypes(6) gss-host-based-services(2)). The constant - * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point - * to that gss_OID_desc. This is a deprecated OID value, and - * implementations wishing to support hostbased-service names - * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID, - * defined below, to identify such names; - * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym - * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input - * parameter, but should not be emitted by GSS-API - * implementations - */ -extern gss_OID GSS_C_NT_HOSTBASED_SERVICE_X; - -/* - * The implementation must reserve static storage for a - * gss_OID_desc object containing the value - * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" - * "\x01\x02\x01\x04"}, corresponding to an - * object-identifier value of {iso(1) member-body(2) - * Unites States(840) mit(113554) infosys(1) gssapi(2) - * generic(1) service_name(4)}. The constant - * GSS_C_NT_HOSTBASED_SERVICE should be initialized - * to point to that gss_OID_desc. - */ -extern gss_OID GSS_C_NT_HOSTBASED_SERVICE; - -/* - * The implementation must reserve static storage for a - * gss_OID_desc object containing the value - * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, - * corresponding to an object identifier value of - * {1(iso), 3(org), 6(dod), 1(internet), 5(security), - * 6(nametypes), 3(gss-anonymous-name)}. The constant - * and GSS_C_NT_ANONYMOUS should be initialized to point - * to that gss_OID_desc. - */ -extern gss_OID GSS_C_NT_ANONYMOUS; - -/* - * The implementation must reserve static storage for a - * gss_OID_desc object containing the value - * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, - * corresponding to an object-identifier value of - * {1(iso), 3(org), 6(dod), 1(internet), 5(security), - * 6(nametypes), 4(gss-api-exported-name)}. The constant - * GSS_C_NT_EXPORT_NAME should be initialized to point - * to that gss_OID_desc. - */ -extern gss_OID GSS_C_NT_EXPORT_NAME; - -/* - * RFC2478, SPNEGO: - * The security mechanism of the initial - * negotiation token is identified by the Object Identifier - * iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2). - */ -extern gss_OID GSS_SPNEGO_MECHANISM; - -/* - * This if for kerberos5 names. - */ - -extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME; -extern gss_OID GSS_KRB5_NT_USER_NAME; -extern gss_OID GSS_KRB5_NT_MACHINE_UID_NAME; -extern gss_OID GSS_KRB5_NT_STRING_UID_NAME; - -extern gss_OID GSS_KRB5_MECHANISM; - -/* for compatibility with MIT api */ - -#define gss_mech_krb5 GSS_KRB5_MECHANISM -#define gss_krb5_nt_general_name GSS_KRB5_NT_PRINCIPAL_NAME +#include <gssapi/gssapi.h> -/* Major status codes */ - -#define GSS_S_COMPLETE 0 - -/* - * Some "helper" definitions to make the status code macros obvious. - */ -#define GSS_C_CALLING_ERROR_OFFSET 24 -#define GSS_C_ROUTINE_ERROR_OFFSET 16 -#define GSS_C_SUPPLEMENTARY_OFFSET 0 -#define GSS_C_CALLING_ERROR_MASK 0377ul -#define GSS_C_ROUTINE_ERROR_MASK 0377ul -#define GSS_C_SUPPLEMENTARY_MASK 0177777ul - -/* - * The macros that test status codes for error conditions. - * Note that the GSS_ERROR() macro has changed slightly from - * the V1 GSSAPI so that it now evaluates its argument - * only once. - */ -#define GSS_CALLING_ERROR(x) \ - (x & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) -#define GSS_ROUTINE_ERROR(x) \ - (x & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) -#define GSS_SUPPLEMENTARY_INFO(x) \ - (x & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) -#define GSS_ERROR(x) \ - (x & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ - (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) - -/* - * Now the actual status code definitions - */ - -/* - * Calling errors: - */ -#define GSS_S_CALL_INACCESSIBLE_READ \ - (1ul << GSS_C_CALLING_ERROR_OFFSET) -#define GSS_S_CALL_INACCESSIBLE_WRITE \ - (2ul << GSS_C_CALLING_ERROR_OFFSET) -#define GSS_S_CALL_BAD_STRUCTURE \ - (3ul << GSS_C_CALLING_ERROR_OFFSET) - -/* - * Routine errors: - */ -#define GSS_S_BAD_MECH (1ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_NAME (2ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_NAMETYPE (3ul << GSS_C_ROUTINE_ERROR_OFFSET) - -#define GSS_S_BAD_BINDINGS (4ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_STATUS (5ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_SIG (6ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_MIC GSS_S_BAD_SIG -#define GSS_S_NO_CRED (7ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_NO_CONTEXT (8ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_DEFECTIVE_TOKEN (9ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_DEFECTIVE_CREDENTIAL (10ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_CREDENTIALS_EXPIRED (11ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_CONTEXT_EXPIRED (12ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_FAILURE (13ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_BAD_QOP (14ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_UNAUTHORIZED (15ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_UNAVAILABLE (16ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_DUPLICATE_ELEMENT (17ul << GSS_C_ROUTINE_ERROR_OFFSET) -#define GSS_S_NAME_NOT_MN (18ul << GSS_C_ROUTINE_ERROR_OFFSET) - -/* - * Supplementary info bits: - */ -#define GSS_S_CONTINUE_NEEDED (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0)) -#define GSS_S_DUPLICATE_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1)) -#define GSS_S_OLD_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2)) -#define GSS_S_UNSEQ_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3)) -#define GSS_S_GAP_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4)) - -/* - * From RFC1964: - * - * 4.1.1. Non-Kerberos-specific codes - */ - -#define GSS_KRB5_S_G_BAD_SERVICE_NAME 1 - /* "No @ in SERVICE-NAME name string" */ -#define GSS_KRB5_S_G_BAD_STRING_UID 2 - /* "STRING-UID-NAME contains nondigits" */ -#define GSS_KRB5_S_G_NOUSER 3 - /* "UID does not resolve to username" */ -#define GSS_KRB5_S_G_VALIDATE_FAILED 4 - /* "Validation error" */ -#define GSS_KRB5_S_G_BUFFER_ALLOC 5 - /* "Couldn't allocate gss_buffer_t data" */ -#define GSS_KRB5_S_G_BAD_MSG_CTX 6 - /* "Message context invalid" */ -#define GSS_KRB5_S_G_WRONG_SIZE 7 - /* "Buffer is the wrong size" */ -#define GSS_KRB5_S_G_BAD_USAGE 8 - /* "Credential usage type is unknown" */ -#define GSS_KRB5_S_G_UNKNOWN_QOP 9 - /* "Unknown quality of protection specified" */ - - /* - * 4.1.2. Kerberos-specific-codes - */ - -#define GSS_KRB5_S_KG_CCACHE_NOMATCH 10 - /* "Principal in credential cache does not match desired name" */ -#define GSS_KRB5_S_KG_KEYTAB_NOMATCH 11 - /* "No principal in keytab matches desired name" */ -#define GSS_KRB5_S_KG_TGT_MISSING 12 - /* "Credential cache has no TGT" */ -#define GSS_KRB5_S_KG_NO_SUBKEY 13 - /* "Authenticator has no subkey" */ -#define GSS_KRB5_S_KG_CONTEXT_ESTABLISHED 14 - /* "Context is already fully established" */ -#define GSS_KRB5_S_KG_BAD_SIGN_TYPE 15 - /* "Unknown signature type in token" */ -#define GSS_KRB5_S_KG_BAD_LENGTH 16 - /* "Invalid field length in token" */ -#define GSS_KRB5_S_KG_CTX_INCOMPLETE 17 - /* "Attempt to use incomplete security context" */ - -/* - * Finally, function prototypes for the GSS-API routines. - */ - - -OM_uint32 gss_acquire_cred - (OM_uint32 * /*minor_status*/, - const gss_name_t /*desired_name*/, - OM_uint32 /*time_req*/, - const gss_OID_set /*desired_mechs*/, - gss_cred_usage_t /*cred_usage*/, - gss_cred_id_t * /*output_cred_handle*/, - gss_OID_set * /*actual_mechs*/, - OM_uint32 * /*time_rec*/ - ); - -OM_uint32 gss_release_cred - (OM_uint32 * /*minor_status*/, - gss_cred_id_t * /*cred_handle*/ - ); - -OM_uint32 gss_init_sec_context - (OM_uint32 * /*minor_status*/, - const gss_cred_id_t /*initiator_cred_handle*/, - gss_ctx_id_t * /*context_handle*/, - const gss_name_t /*target_name*/, - const gss_OID /*mech_type*/, - OM_uint32 /*req_flags*/, - OM_uint32 /*time_req*/, - const gss_channel_bindings_t /*input_chan_bindings*/, - const gss_buffer_t /*input_token*/, - gss_OID * /*actual_mech_type*/, - gss_buffer_t /*output_token*/, - OM_uint32 * /*ret_flags*/, - OM_uint32 * /*time_rec*/ - ); - -OM_uint32 gss_accept_sec_context - (OM_uint32 * /*minor_status*/, - gss_ctx_id_t * /*context_handle*/, - const gss_cred_id_t /*acceptor_cred_handle*/, - const gss_buffer_t /*input_token_buffer*/, - const gss_channel_bindings_t /*input_chan_bindings*/, - gss_name_t * /*src_name*/, - gss_OID * /*mech_type*/, - gss_buffer_t /*output_token*/, - OM_uint32 * /*ret_flags*/, - OM_uint32 * /*time_rec*/, - gss_cred_id_t * /*delegated_cred_handle*/ - ); - -OM_uint32 gss_process_context_token - (OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - const gss_buffer_t /*token_buffer*/ - ); - -OM_uint32 gss_delete_sec_context - (OM_uint32 * /*minor_status*/, - gss_ctx_id_t * /*context_handle*/, - gss_buffer_t /*output_token*/ - ); - -OM_uint32 gss_context_time - (OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - OM_uint32 * /*time_rec*/ - ); - -OM_uint32 gss_get_mic - (OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - gss_qop_t /*qop_req*/, - const gss_buffer_t /*message_buffer*/, - gss_buffer_t /*message_token*/ - ); - -OM_uint32 gss_verify_mic - (OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - const gss_buffer_t /*message_buffer*/, - const gss_buffer_t /*token_buffer*/, - gss_qop_t * /*qop_state*/ - ); - -OM_uint32 gss_wrap - (OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - int /*conf_req_flag*/, - gss_qop_t /*qop_req*/, - const gss_buffer_t /*input_message_buffer*/, - int * /*conf_state*/, - gss_buffer_t /*output_message_buffer*/ - ); - -OM_uint32 gss_unwrap - (OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - const gss_buffer_t /*input_message_buffer*/, - gss_buffer_t /*output_message_buffer*/, - int * /*conf_state*/, - gss_qop_t * /*qop_state*/ - ); - -OM_uint32 gss_display_status - (OM_uint32 * /*minor_status*/, - OM_uint32 /*status_value*/, - int /*status_type*/, - const gss_OID /*mech_type*/, - OM_uint32 * /*message_context*/, - gss_buffer_t /*status_string*/ - ); - -OM_uint32 gss_indicate_mechs - (OM_uint32 * /*minor_status*/, - gss_OID_set * /*mech_set*/ - ); - -OM_uint32 gss_compare_name - (OM_uint32 * /*minor_status*/, - const gss_name_t /*name1*/, - const gss_name_t /*name2*/, - int * /*name_equal*/ - ); - -OM_uint32 gss_display_name - (OM_uint32 * /*minor_status*/, - const gss_name_t /*input_name*/, - gss_buffer_t /*output_name_buffer*/, - gss_OID * /*output_name_type*/ - ); - -OM_uint32 gss_import_name - (OM_uint32 * /*minor_status*/, - const gss_buffer_t /*input_name_buffer*/, - const gss_OID /*input_name_type*/, - gss_name_t * /*output_name*/ - ); - -OM_uint32 gss_export_name - (OM_uint32 * /*minor_status*/, - const gss_name_t /*input_name*/, - gss_buffer_t /*exported_name*/ - ); - -OM_uint32 gss_release_name - (OM_uint32 * /*minor_status*/, - gss_name_t * /*input_name*/ - ); - -OM_uint32 gss_release_buffer - (OM_uint32 * /*minor_status*/, - gss_buffer_t /*buffer*/ - ); - -OM_uint32 gss_release_oid_set - (OM_uint32 * /*minor_status*/, - gss_OID_set * /*set*/ - ); - -OM_uint32 gss_inquire_cred - (OM_uint32 * /*minor_status*/, - const gss_cred_id_t /*cred_handle*/, - gss_name_t * /*name*/, - OM_uint32 * /*lifetime*/, - gss_cred_usage_t * /*cred_usage*/, - gss_OID_set * /*mechanisms*/ - ); - -OM_uint32 gss_inquire_context ( - OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - gss_name_t * /*src_name*/, - gss_name_t * /*targ_name*/, - OM_uint32 * /*lifetime_rec*/, - gss_OID * /*mech_type*/, - OM_uint32 * /*ctx_flags*/, - int * /*locally_initiated*/, - int * /*open_context*/ - ); - -OM_uint32 gsskrb5_wrap_size ( - OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - int /*conf_req_flag*/, - gss_qop_t /*qop_req*/, - OM_uint32 /*req_input_size*/, - OM_uint32 * /*output_size*/ - ); - -OM_uint32 gss_wrap_size_limit ( - OM_uint32 * /*minor_status*/, - const gss_ctx_id_t /*context_handle*/, - int /*conf_req_flag*/, - gss_qop_t /*qop_req*/, - OM_uint32 /*req_output_size*/, - OM_uint32 * /*max_input_size*/ - ); - -OM_uint32 gss_add_cred ( - OM_uint32 * /*minor_status*/, - const gss_cred_id_t /*input_cred_handle*/, - const gss_name_t /*desired_name*/, - const gss_OID /*desired_mech*/, - gss_cred_usage_t /*cred_usage*/, - OM_uint32 /*initiator_time_req*/, - OM_uint32 /*acceptor_time_req*/, - gss_cred_id_t * /*output_cred_handle*/, - gss_OID_set * /*actual_mechs*/, - OM_uint32 * /*initiator_time_rec*/, - OM_uint32 * /*acceptor_time_rec*/ - ); - -OM_uint32 gss_inquire_cred_by_mech ( - OM_uint32 * /*minor_status*/, - const gss_cred_id_t /*cred_handle*/, - const gss_OID /*mech_type*/, - gss_name_t * /*name*/, - OM_uint32 * /*initiator_lifetime*/, - OM_uint32 * /*acceptor_lifetime*/, - gss_cred_usage_t * /*cred_usage*/ - ); - -OM_uint32 gss_export_sec_context ( - OM_uint32 * /*minor_status*/, - gss_ctx_id_t * /*context_handle*/, - gss_buffer_t /*interprocess_token*/ - ); - -OM_uint32 gss_import_sec_context ( - OM_uint32 * /*minor_status*/, - const gss_buffer_t /*interprocess_token*/, - gss_ctx_id_t * /*context_handle*/ - ); - -OM_uint32 gss_create_empty_oid_set ( - OM_uint32 * /*minor_status*/, - gss_OID_set * /*oid_set*/ - ); - -OM_uint32 gss_add_oid_set_member ( - OM_uint32 * /*minor_status*/, - const gss_OID /*member_oid*/, - gss_OID_set * /*oid_set*/ - ); - -OM_uint32 gss_test_oid_set_member ( - OM_uint32 * /*minor_status*/, - const gss_OID /*member*/, - const gss_OID_set /*set*/, - int * /*present*/ - ); - -OM_uint32 gss_inquire_names_for_mech ( - OM_uint32 * /*minor_status*/, - const gss_OID /*mechanism*/, - gss_OID_set * /*name_types*/ - ); - -OM_uint32 gss_inquire_mechs_for_name ( - OM_uint32 * /*minor_status*/, - const gss_name_t /*input_name*/, - gss_OID_set * /*mech_types*/ - ); - -OM_uint32 gss_canonicalize_name ( - OM_uint32 * /*minor_status*/, - const gss_name_t /*input_name*/, - const gss_OID /*mech_type*/, - gss_name_t * /*output_name*/ - ); - -OM_uint32 gss_duplicate_name ( - OM_uint32 * /*minor_status*/, - const gss_name_t /*src_name*/, - gss_name_t * /*dest_name*/ - ); - -/* - * The following routines are obsolete variants of gss_get_mic, - * gss_verify_mic, gss_wrap and gss_unwrap. They should be - * provided by GSSAPI V2 implementations for backwards - * compatibility with V1 applications. Distinct entrypoints - * (as opposed to #defines) should be provided, both to allow - * GSSAPI V1 applications to link against GSSAPI V2 implementations, - * and to retain the slight parameter type differences between the - * obsolete versions of these routines and their current forms. - */ - -OM_uint32 gss_sign - (OM_uint32 * /*minor_status*/, - gss_ctx_id_t /*context_handle*/, - int /*qop_req*/, - gss_buffer_t /*message_buffer*/, - gss_buffer_t /*message_token*/ - ); - -OM_uint32 gss_verify - (OM_uint32 * /*minor_status*/, - gss_ctx_id_t /*context_handle*/, - gss_buffer_t /*message_buffer*/, - gss_buffer_t /*token_buffer*/, - int * /*qop_state*/ - ); - -OM_uint32 gss_seal - (OM_uint32 * /*minor_status*/, - gss_ctx_id_t /*context_handle*/, - int /*conf_req_flag*/, - int /*qop_req*/, - gss_buffer_t /*input_message_buffer*/, - int * /*conf_state*/, - gss_buffer_t /*output_message_buffer*/ - ); - -OM_uint32 gss_unseal - (OM_uint32 * /*minor_status*/, - gss_ctx_id_t /*context_handle*/, - gss_buffer_t /*input_message_buffer*/, - gss_buffer_t /*output_message_buffer*/, - int * /*conf_state*/, - int * /*qop_state*/ - ); - -/* - * kerberos mechanism specific functions - */ - -OM_uint32 -gss_krb5_ccache_name(OM_uint32 * /*minor_status*/, - const char * /*name */, - const char ** /*out_name */); - -OM_uint32 gsskrb5_register_acceptor_identity - (const char */*identity*/); - -OM_uint32 gss_krb5_copy_ccache - (OM_uint32 */*minor*/, - gss_cred_id_t /*cred*/, - struct krb5_ccache_data */*out*/); - -OM_uint32 gss_krb5_copy_service_keyblock - (OM_uint32 *minor_status, - gss_ctx_id_t context_handle, - struct EncryptionKey **out); - -OM_uint32 gss_krb5_import_cred(OM_uint32 *minor_status, - struct krb5_ccache_data * /* id */, - struct Principal * /* keytab_principal */, - struct krb5_keytab_data * /* keytab */, - gss_cred_id_t */* cred */); - -OM_uint32 gss_krb5_get_tkt_flags - (OM_uint32 */*minor*/, - gss_ctx_id_t /*context_handle*/, - OM_uint32 */*tkt_flags*/); - -OM_uint32 -gsskrb5_extract_authz_data_from_sec_context - (OM_uint32 * /*minor_status*/, - gss_ctx_id_t /*context_handle*/, - int /*ad_type*/, - gss_buffer_t /*ad_data*/); -OM_uint32 -gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status, - gss_ctx_id_t context_handle, - time_t *authtime); -OM_uint32 -gsskrb5_get_initiator_subkey - (OM_uint32 * /*minor_status*/, - const gss_ctx_id_t context_handle, - gss_buffer_t /* subkey */); - -#define GSS_C_KRB5_COMPAT_DES3_MIC 1 - -OM_uint32 -gss_krb5_compat_des3_mic(OM_uint32 *, gss_ctx_id_t, int); - -#ifdef __cplusplus -} #endif - -#endif /* GSSAPI_H_ */ diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi.h b/source4/heimdal/lib/gssapi/gssapi/gssapi.h new file mode 100644 index 0000000000..238907653e --- /dev/null +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi.h @@ -0,0 +1,837 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: gssapi.h,v 1.5 2006/10/19 07:11:14 lha Exp $ */ + +#ifndef GSSAPI_GSSAPI_H_ +#define GSSAPI_GSSAPI_H_ + +/* + * First, include stddef.h to get size_t defined. + */ +#include <stddef.h> + +#include <krb5-types.h> + +/* + * Now define the three implementation-dependent types. + */ + +typedef uint32_t OM_uint32; +typedef uint64_t OM_uint64; + +typedef uint32_t gss_uint32; + +struct gss_name_t_desc_struct; +typedef struct gss_name_t_desc_struct *gss_name_t; + +struct gss_ctx_id_t_desc_struct; +typedef struct gss_ctx_id_t_desc_struct *gss_ctx_id_t; + +typedef struct gss_OID_desc_struct { + OM_uint32 length; + void *elements; +} gss_OID_desc, *gss_OID; + +typedef struct gss_OID_set_desc_struct { + size_t count; + gss_OID elements; +} gss_OID_set_desc, *gss_OID_set; + +typedef int gss_cred_usage_t; + +struct gss_cred_id_t_desc_struct; +typedef struct gss_cred_id_t_desc_struct *gss_cred_id_t; + +typedef struct gss_buffer_desc_struct { + size_t length; + void *value; +} gss_buffer_desc, *gss_buffer_t; + +typedef struct gss_channel_bindings_struct { + OM_uint32 initiator_addrtype; + gss_buffer_desc initiator_address; + OM_uint32 acceptor_addrtype; + gss_buffer_desc acceptor_address; + gss_buffer_desc application_data; +} *gss_channel_bindings_t; + +/* GGF extension data types */ +typedef struct gss_buffer_set_desc_struct { + size_t count; + gss_buffer_desc *elements; +} gss_buffer_set_desc, *gss_buffer_set_t; + +/* + * For now, define a QOP-type as an OM_uint32 + */ +typedef OM_uint32 gss_qop_t; + +/* + * Flag bits for context-level services. + */ +#define GSS_C_DELEG_FLAG 1 +#define GSS_C_MUTUAL_FLAG 2 +#define GSS_C_REPLAY_FLAG 4 +#define GSS_C_SEQUENCE_FLAG 8 +#define GSS_C_CONF_FLAG 16 +#define GSS_C_INTEG_FLAG 32 +#define GSS_C_ANON_FLAG 64 +#define GSS_C_PROT_READY_FLAG 128 +#define GSS_C_TRANS_FLAG 256 + +#define GSS_C_DCE_STYLE 4096 +#define GSS_C_IDENTIFY_FLAG 8192 +#define GSS_C_EXTENDED_ERROR_FLAG 16384 + +/* + * Credential usage options + */ +#define GSS_C_BOTH 0 +#define GSS_C_INITIATE 1 +#define GSS_C_ACCEPT 2 + +/* + * Status code types for gss_display_status + */ +#define GSS_C_GSS_CODE 1 +#define GSS_C_MECH_CODE 2 + +/* + * The constant definitions for channel-bindings address families + */ +#define GSS_C_AF_UNSPEC 0 +#define GSS_C_AF_LOCAL 1 +#define GSS_C_AF_INET 2 +#define GSS_C_AF_IMPLINK 3 +#define GSS_C_AF_PUP 4 +#define GSS_C_AF_CHAOS 5 +#define GSS_C_AF_NS 6 +#define GSS_C_AF_NBS 7 +#define GSS_C_AF_ECMA 8 +#define GSS_C_AF_DATAKIT 9 +#define GSS_C_AF_CCITT 10 +#define GSS_C_AF_SNA 11 +#define GSS_C_AF_DECnet 12 +#define GSS_C_AF_DLI 13 +#define GSS_C_AF_LAT 14 +#define GSS_C_AF_HYLINK 15 +#define GSS_C_AF_APPLETALK 16 +#define GSS_C_AF_BSC 17 +#define GSS_C_AF_DSS 18 +#define GSS_C_AF_OSI 19 +#define GSS_C_AF_X25 21 +#define GSS_C_AF_INET6 24 + +#define GSS_C_AF_NULLADDR 255 + +/* + * Various Null values + */ +#define GSS_C_NO_NAME ((gss_name_t) 0) +#define GSS_C_NO_BUFFER ((gss_buffer_t) 0) +#define GSS_C_NO_BUFFER_SET ((gss_buffer_set_t) 0) +#define GSS_C_NO_OID ((gss_OID) 0) +#define GSS_C_NO_OID_SET ((gss_OID_set) 0) +#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0) +#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0) +#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0) +#define GSS_C_EMPTY_BUFFER {0, NULL} + +/* + * Some alternate names for a couple of the above + * values. These are defined for V1 compatibility. + */ +#define GSS_C_NULL_OID GSS_C_NO_OID +#define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET + +/* + * Define the default Quality of Protection for per-message + * services. Note that an implementation that offers multiple + * levels of QOP may define GSS_C_QOP_DEFAULT to be either zero + * (as done here) to mean "default protection", or to a specific + * explicit QOP value. However, a value of 0 should always be + * interpreted by a GSSAPI implementation as a request for the + * default protection level. + */ +#define GSS_C_QOP_DEFAULT 0 + +#define GSS_KRB5_CONF_C_QOP_DES 0x0100 +#define GSS_KRB5_CONF_C_QOP_DES3_KD 0x0200 + +/* + * Expiration time of 2^32-1 seconds means infinite lifetime for a + * credential or security context + */ +#define GSS_C_INDEFINITE 0xfffffffful + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x01"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_USER_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x02"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_MACHINE_UID_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x03"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_STRING_UID_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + * corresponding to an object-identifier value of + * {iso(1) org(3) dod(6) internet(1) security(5) + * nametypes(6) gss-host-based-services(2)). The constant + * GSS_C_NT_HOSTBASED_SERVICE_X should be initialized to point + * to that gss_OID_desc. This is a deprecated OID value, and + * implementations wishing to support hostbased-service names + * should instead use the GSS_C_NT_HOSTBASED_SERVICE OID, + * defined below, to identify such names; + * GSS_C_NT_HOSTBASED_SERVICE_X should be accepted a synonym + * for GSS_C_NT_HOSTBASED_SERVICE when presented as an input + * parameter, but should not be emitted by GSS-API + * implementations + */ +extern gss_OID GSS_C_NT_HOSTBASED_SERVICE_X; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x04"}, corresponding to an + * object-identifier value of {iso(1) member-body(2) + * Unites States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) service_name(4)}. The constant + * GSS_C_NT_HOSTBASED_SERVICE should be initialized + * to point to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_HOSTBASED_SERVICE; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + * corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}. The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_ANONYMOUS; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}. The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_EXPORT_NAME; + +/* + * Digest mechanism + */ + +extern gss_OID GSS_SASL_DIGEST_MD5_MECHANISM; + +/* Major status codes */ + +#define GSS_S_COMPLETE 0 + +/* + * Some "helper" definitions to make the status code macros obvious. + */ +#define GSS_C_CALLING_ERROR_OFFSET 24 +#define GSS_C_ROUTINE_ERROR_OFFSET 16 +#define GSS_C_SUPPLEMENTARY_OFFSET 0 +#define GSS_C_CALLING_ERROR_MASK 0377ul +#define GSS_C_ROUTINE_ERROR_MASK 0377ul +#define GSS_C_SUPPLEMENTARY_MASK 0177777ul + +/* + * The macros that test status codes for error conditions. + * Note that the GSS_ERROR() macro has changed slightly from + * the V1 GSSAPI so that it now evaluates its argument + * only once. + */ +#define GSS_CALLING_ERROR(x) \ + (x & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) +#define GSS_ROUTINE_ERROR(x) \ + (x & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) +#define GSS_SUPPLEMENTARY_INFO(x) \ + (x & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) +#define GSS_ERROR(x) \ + (x & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ + (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) + +/* + * Now the actual status code definitions + */ + +/* + * Calling errors: + */ +#define GSS_S_CALL_INACCESSIBLE_READ \ + (1ul << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_INACCESSIBLE_WRITE \ + (2ul << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_BAD_STRUCTURE \ + (3ul << GSS_C_CALLING_ERROR_OFFSET) + +/* + * Routine errors: + */ +#define GSS_S_BAD_MECH (1ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAME (2ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAMETYPE (3ul << GSS_C_ROUTINE_ERROR_OFFSET) + +#define GSS_S_BAD_BINDINGS (4ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_STATUS (5ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_SIG (6ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_MIC GSS_S_BAD_SIG +#define GSS_S_NO_CRED (7ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NO_CONTEXT (8ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_TOKEN (9ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_CREDENTIAL (10ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CREDENTIALS_EXPIRED (11ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CONTEXT_EXPIRED (12ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_FAILURE (13ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_QOP (14ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAUTHORIZED (15ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAVAILABLE (16ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DUPLICATE_ELEMENT (17ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NAME_NOT_MN (18ul << GSS_C_ROUTINE_ERROR_OFFSET) + +/* + * Supplementary info bits: + */ +#define GSS_S_CONTINUE_NEEDED (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0)) +#define GSS_S_DUPLICATE_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1)) +#define GSS_S_OLD_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2)) +#define GSS_S_UNSEQ_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3)) +#define GSS_S_GAP_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4)) + +/* + * From RFC1964: + * + * 4.1.1. Non-Kerberos-specific codes + */ + +#define GSS_KRB5_S_G_BAD_SERVICE_NAME 1 + /* "No @ in SERVICE-NAME name string" */ +#define GSS_KRB5_S_G_BAD_STRING_UID 2 + /* "STRING-UID-NAME contains nondigits" */ +#define GSS_KRB5_S_G_NOUSER 3 + /* "UID does not resolve to username" */ +#define GSS_KRB5_S_G_VALIDATE_FAILED 4 + /* "Validation error" */ +#define GSS_KRB5_S_G_BUFFER_ALLOC 5 + /* "Couldn't allocate gss_buffer_t data" */ +#define GSS_KRB5_S_G_BAD_MSG_CTX 6 + /* "Message context invalid" */ +#define GSS_KRB5_S_G_WRONG_SIZE 7 + /* "Buffer is the wrong size" */ +#define GSS_KRB5_S_G_BAD_USAGE 8 + /* "Credential usage type is unknown" */ +#define GSS_KRB5_S_G_UNKNOWN_QOP 9 + /* "Unknown quality of protection specified" */ + + /* + * 4.1.2. Kerberos-specific-codes + */ + +#define GSS_KRB5_S_KG_CCACHE_NOMATCH 10 + /* "Principal in credential cache does not match desired name" */ +#define GSS_KRB5_S_KG_KEYTAB_NOMATCH 11 + /* "No principal in keytab matches desired name" */ +#define GSS_KRB5_S_KG_TGT_MISSING 12 + /* "Credential cache has no TGT" */ +#define GSS_KRB5_S_KG_NO_SUBKEY 13 + /* "Authenticator has no subkey" */ +#define GSS_KRB5_S_KG_CONTEXT_ESTABLISHED 14 + /* "Context is already fully established" */ +#define GSS_KRB5_S_KG_BAD_SIGN_TYPE 15 + /* "Unknown signature type in token" */ +#define GSS_KRB5_S_KG_BAD_LENGTH 16 + /* "Invalid field length in token" */ +#define GSS_KRB5_S_KG_CTX_INCOMPLETE 17 + /* "Attempt to use incomplete security context" */ + +/* + * This is used to make sure mechs that don't want to have external + * references don't get any prototypes, and thus can get warnings. + */ + +/* + * Finally, function prototypes for the GSS-API routines. + */ + +OM_uint32 gss_acquire_cred + (OM_uint32 * /*minor_status*/, + const gss_name_t /*desired_name*/, + OM_uint32 /*time_req*/, + const gss_OID_set /*desired_mechs*/, + gss_cred_usage_t /*cred_usage*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * /*time_rec*/ + ); + +OM_uint32 gss_release_cred + (OM_uint32 * /*minor_status*/, + gss_cred_id_t * /*cred_handle*/ + ); + +OM_uint32 gss_init_sec_context + (OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*initiator_cred_handle*/, + gss_ctx_id_t * /*context_handle*/, + const gss_name_t /*target_name*/, + const gss_OID /*mech_type*/, + OM_uint32 /*req_flags*/, + OM_uint32 /*time_req*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + const gss_buffer_t /*input_token*/, + gss_OID * /*actual_mech_type*/, + gss_buffer_t /*output_token*/, + OM_uint32 * /*ret_flags*/, + OM_uint32 * /*time_rec*/ + ); + +OM_uint32 gss_accept_sec_context + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + const gss_cred_id_t /*acceptor_cred_handle*/, + const gss_buffer_t /*input_token_buffer*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + gss_name_t * /*src_name*/, + gss_OID * /*mech_type*/, + gss_buffer_t /*output_token*/, + OM_uint32 * /*ret_flags*/, + OM_uint32 * /*time_rec*/, + gss_cred_id_t * /*delegated_cred_handle*/ + ); + +OM_uint32 gss_process_context_token + (OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t /*token_buffer*/ + ); + +OM_uint32 gss_delete_sec_context + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + gss_buffer_t /*output_token*/ + ); + +OM_uint32 gss_context_time + (OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + OM_uint32 * /*time_rec*/ + ); + +OM_uint32 gss_get_mic + (OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*message_buffer*/, + gss_buffer_t /*message_token*/ + ); + +OM_uint32 gss_verify_mic + (OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t * /*qop_state*/ + ); + +OM_uint32 gss_wrap + (OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t /*output_message_buffer*/ + ); + +OM_uint32 gss_unwrap + (OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + gss_qop_t * /*qop_state*/ + ); + +OM_uint32 gss_display_status + (OM_uint32 * /*minor_status*/, + OM_uint32 /*status_value*/, + int /*status_type*/, + const gss_OID /*mech_type*/, + OM_uint32 * /*message_context*/, + gss_buffer_t /*status_string*/ + ); + +OM_uint32 gss_indicate_mechs + (OM_uint32 * /*minor_status*/, + gss_OID_set * /*mech_set*/ + ); + +OM_uint32 gss_compare_name + (OM_uint32 * /*minor_status*/, + const gss_name_t /*name1*/, + const gss_name_t /*name2*/, + int * /*name_equal*/ + ); + +OM_uint32 gss_display_name + (OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_buffer_t /*output_name_buffer*/, + gss_OID * /*output_name_type*/ + ); + +OM_uint32 gss_import_name + (OM_uint32 * /*minor_status*/, + const gss_buffer_t /*input_name_buffer*/, + const gss_OID /*input_name_type*/, + gss_name_t * /*output_name*/ + ); + +OM_uint32 gss_export_name + (OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_buffer_t /*exported_name*/ + ); + +OM_uint32 gss_release_name + (OM_uint32 * /*minor_status*/, + gss_name_t * /*input_name*/ + ); + +OM_uint32 gss_release_buffer + (OM_uint32 * /*minor_status*/, + gss_buffer_t /*buffer*/ + ); + +OM_uint32 gss_release_oid_set + (OM_uint32 * /*minor_status*/, + gss_OID_set * /*set*/ + ); + +OM_uint32 gss_inquire_cred + (OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + gss_name_t * /*name*/, + OM_uint32 * /*lifetime*/, + gss_cred_usage_t * /*cred_usage*/, + gss_OID_set * /*mechanisms*/ + ); + +OM_uint32 gss_inquire_context ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + gss_name_t * /*src_name*/, + gss_name_t * /*targ_name*/, + OM_uint32 * /*lifetime_rec*/, + gss_OID * /*mech_type*/, + OM_uint32 * /*ctx_flags*/, + int * /*locally_initiated*/, + int * /*open_context*/ + ); + +OM_uint32 gss_wrap_size_limit ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + OM_uint32 /*req_output_size*/, + OM_uint32 * /*max_input_size*/ + ); + +OM_uint32 gss_add_cred ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*input_cred_handle*/, + const gss_name_t /*desired_name*/, + const gss_OID /*desired_mech*/, + gss_cred_usage_t /*cred_usage*/, + OM_uint32 /*initiator_time_req*/, + OM_uint32 /*acceptor_time_req*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * /*initiator_time_rec*/, + OM_uint32 * /*acceptor_time_rec*/ + ); + +OM_uint32 gss_inquire_cred_by_mech ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + const gss_OID /*mech_type*/, + gss_name_t * /*name*/, + OM_uint32 * /*initiator_lifetime*/, + OM_uint32 * /*acceptor_lifetime*/, + gss_cred_usage_t * /*cred_usage*/ + ); + +OM_uint32 gss_export_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + gss_buffer_t /*interprocess_token*/ + ); + +OM_uint32 gss_import_sec_context ( + OM_uint32 * /*minor_status*/, + const gss_buffer_t /*interprocess_token*/, + gss_ctx_id_t * /*context_handle*/ + ); + +OM_uint32 gss_create_empty_oid_set ( + OM_uint32 * /*minor_status*/, + gss_OID_set * /*oid_set*/ + ); + +OM_uint32 gss_add_oid_set_member ( + OM_uint32 * /*minor_status*/, + const gss_OID /*member_oid*/, + gss_OID_set * /*oid_set*/ + ); + +OM_uint32 gss_test_oid_set_member ( + OM_uint32 * /*minor_status*/, + const gss_OID /*member*/, + const gss_OID_set /*set*/, + int * /*present*/ + ); + +OM_uint32 gss_inquire_names_for_mech ( + OM_uint32 * /*minor_status*/, + const gss_OID /*mechanism*/, + gss_OID_set * /*name_types*/ + ); + +OM_uint32 gss_inquire_mechs_for_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_OID_set * /*mech_types*/ + ); + +OM_uint32 gss_canonicalize_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + const gss_OID /*mech_type*/, + gss_name_t * /*output_name*/ + ); + +OM_uint32 gss_duplicate_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*src_name*/, + gss_name_t * /*dest_name*/ + ); + +OM_uint32 gss_duplicate_oid ( + OM_uint32 * /* minor_status */, + gss_OID /* src_oid */, + gss_OID * /* dest_oid */ + ); +OM_uint32 +gss_release_oid + (OM_uint32 * /*minor_status*/, + gss_OID * /* oid */ + ); + +OM_uint32 +gss_oid_to_str( + OM_uint32 * /*minor_status*/, + gss_OID /* oid */, + gss_buffer_t /* str */ + ); + +OM_uint32 +gss_inquire_sec_context_by_oid( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set + ); + +OM_uint32 +gss_set_sec_context_option (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value); + +OM_uint32 +gss_set_cred_option (OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID object, + const gss_buffer_t value); + +int +gss_oid_equal(const gss_OID a, const gss_OID b); + +OM_uint32 +gss_create_empty_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set); + +OM_uint32 +gss_add_buffer_set_member + (OM_uint32 * minor_status, + const gss_buffer_t member_buffer, + gss_buffer_set_t *buffer_set); + +OM_uint32 +gss_release_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set); + +OM_uint32 +gss_inquire_cred_by_oid(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set); + +/* + * The following routines are obsolete variants of gss_get_mic, + * gss_verify_mic, gss_wrap and gss_unwrap. They should be + * provided by GSSAPI V2 implementations for backwards + * compatibility with V1 applications. Distinct entrypoints + * (as opposed to #defines) should be provided, both to allow + * GSSAPI V1 applications to link against GSSAPI V2 implementations, + * and to retain the slight parameter type differences between the + * obsolete versions of these routines and their current forms. + */ + +OM_uint32 gss_sign + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*qop_req*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t /*message_token*/ + ); + +OM_uint32 gss_verify + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t /*token_buffer*/, + int * /*qop_state*/ + ); + +OM_uint32 gss_seal + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + int /*qop_req*/, + gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t /*output_message_buffer*/ + ); + +OM_uint32 gss_unseal + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + int * /*qop_state*/ + ); + +/* + * + */ + +OM_uint32 +gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set); + +OM_uint32 +gss_encapsulate_token(gss_buffer_t /* input_token */, + gss_OID /* oid */, + gss_buffer_t /* output_token */); + +OM_uint32 +gss_decapsulate_token(gss_buffer_t /* input_token */, + gss_OID /* oid */, + gss_buffer_t /* output_token */); + + + +#ifdef __cplusplus +} +#endif + +#include <gssapi/gssapi_krb5.h> +#include <gssapi/gssapi_spnego.h> + +#endif /* GSSAPI_GSSAPI_H_ */ diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h b/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h new file mode 100644 index 0000000000..8c025c8366 --- /dev/null +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h @@ -0,0 +1,209 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: gssapi_krb5.h,v 1.10 2006/10/20 22:04:03 lha Exp $ */ + +#ifndef GSSAPI_KRB5_H_ +#define GSSAPI_KRB5_H_ + +#include <gssapi/gssapi.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * This is for kerberos5 names. + */ + +extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME; +extern gss_OID GSS_KRB5_NT_USER_NAME; +extern gss_OID GSS_KRB5_NT_MACHINE_UID_NAME; +extern gss_OID GSS_KRB5_NT_STRING_UID_NAME; + +extern gss_OID GSS_KRB5_MECHANISM; + +/* for compatibility with MIT api */ + +#define gss_mech_krb5 GSS_KRB5_MECHANISM +#define gss_krb5_nt_general_name GSS_KRB5_NT_PRINCIPAL_NAME + +/* Extensions set contexts options */ +extern gss_OID GSS_KRB5_COPY_CCACHE_X; +extern gss_OID GSS_KRB5_COMPAT_DES3_MIC_X; +extern gss_OID GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X; +extern gss_OID GSS_KRB5_SET_DNS_CANONICALIZE_X; +extern gss_OID GSS_KRB5_SEND_TO_KDC_X; +/* Extensions inquire context */ +extern gss_OID GSS_KRB5_GET_TKT_FLAGS_X; +extern gss_OID GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X; +extern gss_OID GSS_C_PEER_HAS_UPDATED_SPNEGO; +extern gss_OID GSS_KRB5_EXPORT_LUCID_CONTEXT_X; +extern gss_OID GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X; +extern gss_OID GSS_KRB5_GET_SUBKEY_X; +extern gss_OID GSS_KRB5_GET_INITIATOR_SUBKEY_X; +extern gss_OID GSS_KRB5_GET_ACCEPTOR_SUBKEY_X; +extern gss_OID GSS_KRB5_GET_AUTHTIME_X; +extern gss_OID GSS_KRB5_GET_SERVICE_KEYBLOCK_X; +/* Extensions creds */ +extern gss_OID GSS_KRB5_IMPORT_CRED_X; + +/* + * kerberos mechanism specific functions + */ + +struct krb5_keytab_data; +struct krb5_ccache_data; +struct Principal; + +OM_uint32 +gss_krb5_ccache_name(OM_uint32 * /*minor_status*/, + const char * /*name */, + const char ** /*out_name */); + +OM_uint32 gsskrb5_register_acceptor_identity + (const char */*identity*/); + +OM_uint32 gss_krb5_copy_ccache + (OM_uint32 */*minor*/, + gss_cred_id_t /*cred*/, + struct krb5_ccache_data */*out*/); + +OM_uint32 +gss_krb5_import_cred(OM_uint32 */*minor*/, + struct krb5_ccache_data * /*in*/, + struct Principal * /*keytab_principal*/, + struct krb5_keytab_data * /*keytab*/, + gss_cred_id_t */*out*/); + +OM_uint32 gss_krb5_get_tkt_flags + (OM_uint32 */*minor*/, + gss_ctx_id_t /*context_handle*/, + OM_uint32 */*tkt_flags*/); + +OM_uint32 +gsskrb5_extract_authz_data_from_sec_context + (OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*ad_type*/, + gss_buffer_t /*ad_data*/); + +OM_uint32 +gsskrb5_set_dns_canonicalize(int); + +struct gsskrb5_send_to_kdc { + void *func; + void *ptr; +}; + +OM_uint32 +gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *); + +OM_uint32 +gsskrb5_extract_authtime_from_sec_context(OM_uint32 *, gss_ctx_id_t, time_t *); + +struct EncryptionKey; + +OM_uint32 +gsskrb5_extract_service_keyblock(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + struct EncryptionKey **out); +OM_uint32 +gsskrb5_get_initiator_subkey(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + struct EncryptionKey **out); +OM_uint32 +gsskrb5_get_subkey(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + struct EncryptionKey **out); + +/* + * Lucid - NFSv4 interface to GSS-API KRB5 to expose key material to + * do GSS content token handling in-kernel. + */ + +typedef struct gss_krb5_lucid_key { + OM_uint32 type; + OM_uint32 length; + void * data; +} gss_krb5_lucid_key_t; + +typedef struct gss_krb5_rfc1964_keydata { + OM_uint32 sign_alg; + OM_uint32 seal_alg; + gss_krb5_lucid_key_t ctx_key; +} gss_krb5_rfc1964_keydata_t; + +typedef struct gss_krb5_cfx_keydata { + OM_uint32 have_acceptor_subkey; + gss_krb5_lucid_key_t ctx_key; + gss_krb5_lucid_key_t acceptor_subkey; +} gss_krb5_cfx_keydata_t; + +typedef struct gss_krb5_lucid_context_v1 { + OM_uint32 version; + OM_uint32 initiate; + OM_uint32 endtime; + OM_uint64 send_seq; + OM_uint64 recv_seq; + OM_uint32 protocol; + gss_krb5_rfc1964_keydata_t rfc1964_kd; + gss_krb5_cfx_keydata_t cfx_kd; +} gss_krb5_lucid_context_v1_t; + +typedef struct gss_krb5_lucid_context_version { + OM_uint32 version; /* Structure version number */ +} gss_krb5_lucid_context_version_t; + +/* + * Function declarations + */ + +OM_uint32 +gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + OM_uint32 version, + void **kctx); + + +OM_uint32 +gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, + void *kctx); + + + +#ifdef __cplusplus +} +#endif + +#endif /* GSSAPI_SPNEGO_H_ */ diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h b/source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h new file mode 100644 index 0000000000..0a856e39aa --- /dev/null +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi_spnego.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: gssapi_spnego.h,v 1.1 2006/10/07 22:26:21 lha Exp $ */ + +#ifndef GSSAPI_SPNEGO_H_ +#define GSSAPI_SPNEGO_H_ + +#include <gssapi.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * RFC2478, SPNEGO: + * The security mechanism of the initial + * negotiation token is identified by the Object Identifier + * iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2). + */ +extern gss_OID GSS_SPNEGO_MECHANISM; +#define gss_mech_spnego GSS_SPNEGO_MECHANISM + +#ifdef __cplusplus +} +#endif + +#endif /* GSSAPI_SPNEGO_H_ */ diff --git a/source4/heimdal/lib/gssapi/gssapi_locl.h b/source4/heimdal/lib/gssapi/gssapi_locl.h deleted file mode 100644 index 81169a8500..0000000000 --- a/source4/heimdal/lib/gssapi/gssapi_locl.h +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -/* $Id: gssapi_locl.h,v 1.45 2006/05/04 11:56:14 lha Exp $ */ - -#ifndef GSSAPI_LOCL_H -#define GSSAPI_LOCL_H - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <krb5_locl.h> -#include <gssapi.h> -#include <assert.h> - -#include "cfx.h" -#include "arcfour.h" - -#include "spnego_asn1.h" - -/* - * - */ - -struct gss_msg_order; - -typedef struct gss_ctx_id_t_desc_struct { - struct krb5_auth_context_data *auth_context; - gss_name_t source, target; - enum gss_ctx_id_t_state { - INITIATOR_START = 1, INITIATOR_WAIT_FOR_MUTAL = 2, INITIATOR_READY= 3, - ACCEPTOR_START = 11, ACCEPTOR_WAIT_FOR_DCESTYLE = 12, ACCEPTOR_READY = 13 - } state; - OM_uint32 flags; - enum {LOCAL = 1, - OPEN = 2, - COMPAT_OLD_DES3 = 4, - COMPAT_OLD_DES3_SELECTED = 8, - ACCEPTOR_SUBKEY = 16 - } more_flags; - struct krb5_ticket *ticket; - krb5_keyblock *service_keyblock; - krb5_data fwd_data; - OM_uint32 lifetime; - HEIMDAL_MUTEX ctx_id_mutex; - struct gss_msg_order *order; -} gss_ctx_id_t_desc; - -typedef struct gss_cred_id_t_desc_struct { - gss_name_t principal; - int cred_flags; -#define GSS_CF_DESTROY_CRED_ON_RELEASE 1 - struct krb5_keytab_data *keytab; - OM_uint32 lifetime; - gss_cred_usage_t usage; - gss_OID_set mechanisms; - struct krb5_ccache_data *ccache; - HEIMDAL_MUTEX cred_id_mutex; -} gss_cred_id_t_desc; - -/* - * - */ - -extern krb5_context gssapi_krb5_context; - -extern krb5_keytab gssapi_krb5_keytab; -extern HEIMDAL_MUTEX gssapi_keytab_mutex; - -struct gssapi_thr_context { - HEIMDAL_MUTEX mutex; - char *error_string; -}; - -/* - * Prototypes - */ - -krb5_error_code gssapi_krb5_init (void); - -krb5_error_code gssapi_krb5_init_ev (void *); - -#define GSSAPI_KRB5_INIT() do { \ - krb5_error_code kret_gss_init; \ - if((kret_gss_init = gssapi_krb5_init ()) != 0) { \ - *minor_status = kret_gss_init; \ - return GSS_S_FAILURE; \ - } \ -} while (0) - -struct gssapi_thr_context * -gssapi_get_thread_context(int); - -OM_uint32 -_gsskrb5_create_ctx( - OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - const gss_channel_bindings_t input_chan_bindings, - enum gss_ctx_id_t_state state); - -void -gsskrb5_is_cfx(gss_ctx_id_t, int *); - -OM_uint32 -gssapi_krb5_create_8003_checksum ( - OM_uint32 *minor_status, - const gss_channel_bindings_t input_chan_bindings, - OM_uint32 flags, - const krb5_data *fwd_data, - Checksum *result); - -OM_uint32 -gssapi_krb5_verify_8003_checksum ( - OM_uint32 *minor_status, - const gss_channel_bindings_t input_chan_bindings, - const Checksum *cksum, - OM_uint32 *flags, - krb5_data *fwd_data); - -void -_gssapi_encap_length (size_t data_len, - size_t *len, - size_t *total_len, - const gss_OID mech); - -void -gssapi_krb5_encap_length (size_t data_len, - size_t *len, - size_t *total_len, - const gss_OID mech); - - - -OM_uint32 -_gssapi_encapsulate(OM_uint32 *minor_status, - const krb5_data *in_data, - gss_buffer_t output_token, - const gss_OID mech); - - -OM_uint32 -gssapi_krb5_encapsulate(OM_uint32 *minor_status, - const krb5_data *in_data, - gss_buffer_t output_token, - const u_char *type, - const gss_OID mech); - -OM_uint32 -gssapi_krb5_decapsulate(OM_uint32 *minor_status, - gss_buffer_t input_token_buffer, - krb5_data *out_data, - const char *type, - gss_OID oid); - -u_char * -gssapi_krb5_make_header (u_char *p, - size_t len, - const u_char *type, - const gss_OID mech); - -u_char * -_gssapi_make_mech_header(u_char *p, - size_t len, - const gss_OID mech); - -OM_uint32 -_gssapi_verify_mech_header(u_char **str, - size_t total_len, - gss_OID oid); - -OM_uint32 -gssapi_krb5_verify_header(u_char **str, - size_t total_len, - const u_char *type, - gss_OID oid); - -OM_uint32 -_gssapi_decapsulate(OM_uint32 *minor_status, - gss_buffer_t input_token_buffer, - krb5_data *out_data, - const gss_OID mech); - - -ssize_t -gssapi_krb5_get_mech (const u_char *, size_t, const u_char **); - -OM_uint32 -_gssapi_verify_pad(gss_buffer_t, size_t, size_t *); - -OM_uint32 -gss_verify_mic_internal(OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, - const gss_buffer_t message_buffer, - const gss_buffer_t token_buffer, - gss_qop_t * qop_state, - char * type); - -OM_uint32 -gss_krb5_get_subkey(const gss_ctx_id_t context_handle, - krb5_keyblock **key); - -krb5_error_code -gss_address_to_krb5addr(OM_uint32 gss_addr_type, - gss_buffer_desc *gss_addr, - int16_t port, - krb5_address *address); - -/* sec_context flags */ - -#define SC_LOCAL_ADDRESS 0x01 -#define SC_REMOTE_ADDRESS 0x02 -#define SC_KEYBLOCK 0x04 -#define SC_LOCAL_SUBKEY 0x08 -#define SC_REMOTE_SUBKEY 0x10 - -int -gss_oid_equal(const gss_OID a, const gss_OID b); - -void -gssapi_krb5_clear_status (void); - -void -gssapi_krb5_set_status (const char *fmt, ...); - -void -gssapi_krb5_set_error_string (void); - -char * -gssapi_krb5_get_error_string (void); - -OM_uint32 -_gss_DES3_get_mic_compat(OM_uint32 *, gss_ctx_id_t); - -OM_uint32 -_gss_spnego_require_mechlist_mic(OM_uint32 *, gss_ctx_id_t, krb5_boolean *); - -krb5_error_code -_gss_check_compat(OM_uint32 *, gss_name_t, const char *, - krb5_boolean *, krb5_boolean); - -OM_uint32 -gssapi_lifetime_left(OM_uint32 *, OM_uint32, OM_uint32 *); - -OM_uint32 -_gssapi_krb5_ccache_lifetime(OM_uint32 *, krb5_ccache, - krb5_principal, OM_uint32 *); - -/* sequence */ - -OM_uint32 -_gssapi_msg_order_create(OM_uint32 *, struct gss_msg_order **, - OM_uint32, OM_uint32, OM_uint32, int); -OM_uint32 -_gssapi_msg_order_destroy(struct gss_msg_order **); - -OM_uint32 -_gssapi_msg_order_check(struct gss_msg_order *, OM_uint32); - -OM_uint32 -_gssapi_msg_order_f(OM_uint32); - -OM_uint32 -_gssapi_msg_order_import(OM_uint32 *, krb5_storage *, - struct gss_msg_order **); - -krb5_error_code -_gssapi_msg_order_export(krb5_storage *, struct gss_msg_order *); - - -/* 8003 */ - -krb5_error_code -gssapi_encode_om_uint32(OM_uint32, u_char *); - -krb5_error_code -gssapi_encode_be_om_uint32(OM_uint32, u_char *); - -krb5_error_code -gssapi_decode_om_uint32(const void *, OM_uint32 *); - -krb5_error_code -gssapi_decode_be_om_uint32(const void *, OM_uint32 *); - -#endif diff --git a/source4/heimdal/lib/gssapi/gssapi_mech.h b/source4/heimdal/lib/gssapi/gssapi_mech.h new file mode 100644 index 0000000000..a05919b510 --- /dev/null +++ b/source4/heimdal/lib/gssapi/gssapi_mech.h @@ -0,0 +1,348 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/mech_switch.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#ifndef GSSAPI_MECH_H +#define GSSAPI_MECH_H 1 + +#include <gssapi.h> + +typedef OM_uint32 _gss_acquire_cred_t + (OM_uint32 *, /* minor_status */ + const gss_name_t, /* desired_name */ + OM_uint32, /* time_req */ + const gss_OID_set, /* desired_mechs */ + gss_cred_usage_t, /* cred_usage */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 * /* time_rec */ + ); + +typedef OM_uint32 _gss_release_cred_t + (OM_uint32 *, /* minor_status */ + gss_cred_id_t * /* cred_handle */ + ); + +typedef OM_uint32 _gss_init_sec_context_t + (OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* initiator_cred_handle */ + gss_ctx_id_t *, /* context_handle */ + const gss_name_t, /* target_name */ + const gss_OID, /* mech_type */ + OM_uint32, /* req_flags */ + OM_uint32, /* time_req */ + const gss_channel_bindings_t, + /* input_chan_bindings */ + const gss_buffer_t, /* input_token */ + gss_OID *, /* actual_mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32 *, /* ret_flags */ + OM_uint32 * /* time_rec */ + ); + +typedef OM_uint32 _gss_accept_sec_context_t + (OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + const gss_cred_id_t, /* acceptor_cred_handle */ + const gss_buffer_t, /* input_token_buffer */ + const gss_channel_bindings_t, + /* input_chan_bindings */ + gss_name_t *, /* src_name */ + gss_OID *, /* mech_type */ + gss_buffer_t, /* output_token */ + OM_uint32 *, /* ret_flags */ + OM_uint32 *, /* time_rec */ + gss_cred_id_t * /* delegated_cred_handle */ + ); + +typedef OM_uint32 _gss_process_context_token_t + (OM_uint32 *, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + const gss_buffer_t /* token_buffer */ + ); + +typedef OM_uint32 _gss_delete_sec_context_t + (OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_buffer_t /* output_token */ + ); + +typedef OM_uint32 _gss_context_time_t + (OM_uint32 *, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + OM_uint32 * /* time_rec */ + ); + +typedef OM_uint32 _gss_get_mic_t + (OM_uint32 *, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + gss_qop_t, /* qop_req */ + const gss_buffer_t, /* message_buffer */ + gss_buffer_t /* message_token */ + ); + +typedef OM_uint32 _gss_verify_mic_t + (OM_uint32 *, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + const gss_buffer_t, /* message_buffer */ + const gss_buffer_t, /* token_buffer */ + gss_qop_t * /* qop_state */ + ); + +typedef OM_uint32 _gss_wrap_t + (OM_uint32 *, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + const gss_buffer_t, /* input_message_buffer */ + int *, /* conf_state */ + gss_buffer_t /* output_message_buffer */ + ); + +typedef OM_uint32 _gss_unwrap_t + (OM_uint32 *, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + const gss_buffer_t, /* input_message_buffer */ + gss_buffer_t, /* output_message_buffer */ + int *, /* conf_state */ + gss_qop_t * /* qop_state */ + ); + +typedef OM_uint32 _gss_display_status_t + (OM_uint32 *, /* minor_status */ + OM_uint32, /* status_value */ + int, /* status_type */ + const gss_OID, /* mech_type */ + OM_uint32 *, /* message_context */ + gss_buffer_t /* status_string */ + ); + +typedef OM_uint32 _gss_indicate_mechs_t + (OM_uint32 *, /* minor_status */ + gss_OID_set * /* mech_set */ + ); + +typedef OM_uint32 _gss_compare_name_t + (OM_uint32 *, /* minor_status */ + const gss_name_t, /* name1 */ + const gss_name_t, /* name2 */ + int * /* name_equal */ + ); + +typedef OM_uint32 _gss_display_name_t + (OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + gss_buffer_t, /* output_name_buffer */ + gss_OID * /* output_name_type */ + ); + +typedef OM_uint32 _gss_import_name_t + (OM_uint32 *, /* minor_status */ + const gss_buffer_t, /* input_name_buffer */ + const gss_OID, /* input_name_type */ + gss_name_t * /* output_name */ + ); + +typedef OM_uint32 _gss_export_name_t + (OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + gss_buffer_t /* exported_name */ + ); + +typedef OM_uint32 _gss_release_name_t + (OM_uint32 *, /* minor_status */ + gss_name_t * /* input_name */ + ); + +typedef OM_uint32 _gss_inquire_cred_t + (OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* cred_handle */ + gss_name_t *, /* name */ + OM_uint32 *, /* lifetime */ + gss_cred_usage_t *, /* cred_usage */ + gss_OID_set * /* mechanisms */ + ); + +typedef OM_uint32 _gss_inquire_context_t + (OM_uint32 *, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + gss_name_t *, /* src_name */ + gss_name_t *, /* targ_name */ + OM_uint32 *, /* lifetime_rec */ + gss_OID *, /* mech_type */ + OM_uint32 *, /* ctx_flags */ + int *, /* locally_initiated */ + int * /* open */ + ); + +typedef OM_uint32 _gss_wrap_size_limit_t + (OM_uint32 *, /* minor_status */ + const gss_ctx_id_t, /* context_handle */ + int, /* conf_req_flag */ + gss_qop_t, /* qop_req */ + OM_uint32, /* req_output_size */ + OM_uint32 * /* max_input_size */ + ); + +typedef OM_uint32 _gss_add_cred_t ( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* input_cred_handle */ + const gss_name_t, /* desired_name */ + const gss_OID, /* desired_mech */ + gss_cred_usage_t, /* cred_usage */ + OM_uint32, /* initiator_time_req */ + OM_uint32, /* acceptor_time_req */ + gss_cred_id_t *, /* output_cred_handle */ + gss_OID_set *, /* actual_mechs */ + OM_uint32 *, /* initiator_time_rec */ + OM_uint32 * /* acceptor_time_rec */ + ); + +typedef OM_uint32 _gss_inquire_cred_by_mech_t ( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* cred_handle */ + const gss_OID, /* mech_type */ + gss_name_t *, /* name */ + OM_uint32 *, /* initiator_lifetime */ + OM_uint32 *, /* acceptor_lifetime */ + gss_cred_usage_t * /* cred_usage */ + ); + +typedef OM_uint32 _gss_export_sec_context_t ( + OM_uint32 *, /* minor_status */ + gss_ctx_id_t *, /* context_handle */ + gss_buffer_t /* interprocess_token */ + ); + +typedef OM_uint32 _gss_import_sec_context_t ( + OM_uint32 *, /* minor_status */ + const gss_buffer_t, /* interprocess_token */ + gss_ctx_id_t * /* context_handle */ + ); + +typedef OM_uint32 _gss_inquire_names_for_mech_t ( + OM_uint32 *, /* minor_status */ + const gss_OID, /* mechanism */ + gss_OID_set * /* name_types */ + ); + +typedef OM_uint32 _gss_inquire_mechs_for_name_t ( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + gss_OID_set * /* mech_types */ + ); + +typedef OM_uint32 _gss_canonicalize_name_t ( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* input_name */ + const gss_OID, /* mech_type */ + gss_name_t * /* output_name */ + ); + +typedef OM_uint32 _gss_duplicate_name_t ( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* src_name */ + gss_name_t * /* dest_name */ + ); + +typedef OM_uint32 _gss_inquire_sec_context_by_oid ( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set + ); + +typedef OM_uint32 _gss_inquire_cred_by_oid ( + OM_uint32 *minor_status, + const gss_cred_id_t cred, + const gss_OID desired_object, + gss_buffer_set_t *data_set + ); + +typedef OM_uint32 _gss_set_sec_context_option ( + OM_uint32 *minor_status, + gss_ctx_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value + ); + +typedef OM_uint32 _gss_set_cred_option ( + OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value + ); + + +#define GMI_VERSION 1 + +typedef struct gssapi_mech_interface_desc { + unsigned gm_version; + const char *gm_name; + gss_OID_desc gm_mech_oid; + _gss_acquire_cred_t *gm_acquire_cred; + _gss_release_cred_t *gm_release_cred; + _gss_init_sec_context_t *gm_init_sec_context; + _gss_accept_sec_context_t *gm_accept_sec_context; + _gss_process_context_token_t *gm_process_context_token; + _gss_delete_sec_context_t *gm_delete_sec_context; + _gss_context_time_t *gm_context_time; + _gss_get_mic_t *gm_get_mic; + _gss_verify_mic_t *gm_verify_mic; + _gss_wrap_t *gm_wrap; + _gss_unwrap_t *gm_unwrap; + _gss_display_status_t *gm_display_status; + _gss_indicate_mechs_t *gm_indicate_mechs; + _gss_compare_name_t *gm_compare_name; + _gss_display_name_t *gm_display_name; + _gss_import_name_t *gm_import_name; + _gss_export_name_t *gm_export_name; + _gss_release_name_t *gm_release_name; + _gss_inquire_cred_t *gm_inquire_cred; + _gss_inquire_context_t *gm_inquire_context; + _gss_wrap_size_limit_t *gm_wrap_size_limit; + _gss_add_cred_t *gm_add_cred; + _gss_inquire_cred_by_mech_t *gm_inquire_cred_by_mech; + _gss_export_sec_context_t *gm_export_sec_context; + _gss_import_sec_context_t *gm_import_sec_context; + _gss_inquire_names_for_mech_t *gm_inquire_names_for_mech; + _gss_inquire_mechs_for_name_t *gm_inquire_mechs_for_name; + _gss_canonicalize_name_t *gm_canonicalize_name; + _gss_duplicate_name_t *gm_duplicate_name; + _gss_inquire_sec_context_by_oid *gm_inquire_sec_context_by_oid; + _gss_inquire_cred_by_oid *gm_inquire_cred_by_oid; + _gss_set_sec_context_option *gm_set_sec_context_option; + _gss_set_cred_option *gm_set_cred_option; +} gssapi_mech_interface_desc, *gssapi_mech_interface; + +gssapi_mech_interface +__gss_get_mechanism(gss_OID /* oid */); + +gssapi_mech_interface __gss_spnego_initialize(void); +gssapi_mech_interface __gss_krb5_initialize(void); + +#endif /* GSSAPI_MECH_H */ diff --git a/source4/heimdal/lib/gssapi/init_sec_context.c b/source4/heimdal/lib/gssapi/init_sec_context.c deleted file mode 100644 index 4f0d237241..0000000000 --- a/source4/heimdal/lib/gssapi/init_sec_context.c +++ /dev/null @@ -1,1261 +0,0 @@ -/* - * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "gssapi_locl.h" - -RCSID("$Id: init_sec_context.c,v 1.63 2006/05/05 10:27:13 lha Exp $"); - -/* - * copy the addresses from `input_chan_bindings' (if any) to - * the auth context `ac' - */ - -static OM_uint32 -set_addresses (krb5_auth_context ac, - const gss_channel_bindings_t input_chan_bindings) -{ - /* Port numbers are expected to be in application_data.value, - * initator's port first */ - - krb5_address initiator_addr, acceptor_addr; - krb5_error_code kret; - - if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS - || input_chan_bindings->application_data.length != - 2 * sizeof(ac->local_port)) - return 0; - - memset(&initiator_addr, 0, sizeof(initiator_addr)); - memset(&acceptor_addr, 0, sizeof(acceptor_addr)); - - ac->local_port = - *(int16_t *) input_chan_bindings->application_data.value; - - ac->remote_port = - *((int16_t *) input_chan_bindings->application_data.value + 1); - - kret = gss_address_to_krb5addr(input_chan_bindings->acceptor_addrtype, - &input_chan_bindings->acceptor_address, - ac->remote_port, - &acceptor_addr); - if (kret) - return kret; - - kret = gss_address_to_krb5addr(input_chan_bindings->initiator_addrtype, - &input_chan_bindings->initiator_address, - ac->local_port, - &initiator_addr); - if (kret) { - krb5_free_address (gssapi_krb5_context, &acceptor_addr); - return kret; - } - - kret = krb5_auth_con_setaddrs(gssapi_krb5_context, - ac, - &initiator_addr, /* local address */ - &acceptor_addr); /* remote address */ - - krb5_free_address (gssapi_krb5_context, &initiator_addr); - krb5_free_address (gssapi_krb5_context, &acceptor_addr); - -#if 0 - free(input_chan_bindings->application_data.value); - input_chan_bindings->application_data.value = NULL; - input_chan_bindings->application_data.length = 0; -#endif - - return kret; -} - -OM_uint32 -_gsskrb5_create_ctx( - OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - const gss_channel_bindings_t input_chan_bindings, - enum gss_ctx_id_t_state state) -{ - krb5_error_code kret; - - *context_handle = malloc(sizeof(**context_handle)); - if (*context_handle == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - (*context_handle)->auth_context = NULL; - (*context_handle)->source = NULL; - (*context_handle)->target = NULL; - (*context_handle)->state = state; - (*context_handle)->flags = 0; - (*context_handle)->more_flags = 0; - (*context_handle)->service_keyblock = NULL; - (*context_handle)->ticket = NULL; - krb5_data_zero(&(*context_handle)->fwd_data); - (*context_handle)->lifetime = GSS_C_INDEFINITE; - (*context_handle)->order = NULL; - HEIMDAL_MUTEX_init(&(*context_handle)->ctx_id_mutex); - - kret = krb5_auth_con_init (gssapi_krb5_context, - &(*context_handle)->auth_context); - if (kret) { - *minor_status = kret; - gssapi_krb5_set_error_string (); - - HEIMDAL_MUTEX_destroy(&(*context_handle)->ctx_id_mutex); - - return GSS_S_FAILURE; - } - - kret = set_addresses((*context_handle)->auth_context, - input_chan_bindings); - if (kret) { - *minor_status = kret; - - HEIMDAL_MUTEX_destroy(&(*context_handle)->ctx_id_mutex); - - krb5_auth_con_free(gssapi_krb5_context, (*context_handle)->auth_context); - - return GSS_S_BAD_BINDINGS; - } - - /* - * We need a sequence number - */ - - krb5_auth_con_addflags(gssapi_krb5_context, - (*context_handle)->auth_context, - KRB5_AUTH_CONTEXT_DO_SEQUENCE, - NULL); - - return GSS_S_COMPLETE; -} - -static OM_uint32 -gsskrb5_get_creds( - OM_uint32 * minor_status, - krb5_ccache ccache, - gss_ctx_id_t * context_handle, - const gss_name_t target_name, - OM_uint32 time_req, - OM_uint32 * time_rec, - krb5_creds ** cred) -{ - OM_uint32 ret; - krb5_error_code kret; - krb5_creds this_cred; - OM_uint32 lifetime_rec; - - *cred = NULL; - - kret = krb5_cc_get_principal(gssapi_krb5_context, - ccache, - &(*context_handle)->source); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - kret = krb5_copy_principal(gssapi_krb5_context, - target_name, - &(*context_handle)->target); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - memset(&this_cred, 0, sizeof(this_cred)); - this_cred.client = (*context_handle)->source; - this_cred.server = (*context_handle)->target; - - if (time_req && time_req != GSS_C_INDEFINITE) { - krb5_timestamp ts; - - krb5_timeofday (gssapi_krb5_context, &ts); - this_cred.times.endtime = ts + time_req; - } else { - this_cred.times.endtime = 0; - } - - this_cred.session.keytype = KEYTYPE_NULL; - - kret = krb5_get_credentials(gssapi_krb5_context, - 0, - ccache, - &this_cred, - cred); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - (*context_handle)->lifetime = (*cred)->times.endtime; - - ret = gssapi_lifetime_left(minor_status, - (*context_handle)->lifetime, - &lifetime_rec); - if (ret) return ret; - - if (lifetime_rec == 0) { - *minor_status = 0; - return GSS_S_CONTEXT_EXPIRED; - } - - if (time_rec) *time_rec = lifetime_rec; - - return GSS_S_COMPLETE; -} - -static OM_uint32 -gsskrb5_initiator_ready( - OM_uint32 * minor_status, - gss_ctx_id_t * context_handle) -{ - OM_uint32 ret; - int32_t seq_number; - int is_cfx = 0; - OM_uint32 flags = (*context_handle)->flags; - - krb5_auth_getremoteseqnumber (gssapi_krb5_context, - (*context_handle)->auth_context, - &seq_number); - - gsskrb5_is_cfx(*context_handle, &is_cfx); - - ret = _gssapi_msg_order_create(minor_status, - &(*context_handle)->order, - _gssapi_msg_order_f(flags), - seq_number, 0, is_cfx); - if (ret) return ret; - - (*context_handle)->state = INITIATOR_READY; - (*context_handle)->more_flags |= OPEN; - - return GSS_S_COMPLETE; -} - -/* - * handle delegated creds in init-sec-context - */ - -static void -do_delegation (krb5_auth_context ac, - krb5_ccache ccache, - krb5_creds *cred, - const gss_name_t target_name, - krb5_data *fwd_data, - OM_uint32 *flags) -{ - krb5_creds creds; - krb5_kdc_flags fwd_flags; - krb5_error_code kret; - - memset (&creds, 0, sizeof(creds)); - krb5_data_zero (fwd_data); - - kret = krb5_cc_get_principal(gssapi_krb5_context, ccache, &creds.client); - if (kret) - goto out; - - kret = krb5_build_principal(gssapi_krb5_context, - &creds.server, - strlen(creds.client->realm), - creds.client->realm, - KRB5_TGS_NAME, - creds.client->realm, - NULL); - if (kret) - goto out; - - creds.times.endtime = 0; - - fwd_flags.i = 0; - fwd_flags.b.forwarded = 1; - fwd_flags.b.forwardable = 1; - - if ( /*target_name->name.name_type != KRB5_NT_SRV_HST ||*/ - target_name->name.name_string.len < 2) - goto out; - - kret = krb5_get_forwarded_creds(gssapi_krb5_context, - ac, - ccache, - fwd_flags.i, - target_name->name.name_string.val[1], - &creds, - fwd_data); - - out: - if (kret) - *flags &= ~GSS_C_DELEG_FLAG; - else - *flags |= GSS_C_DELEG_FLAG; - - if (creds.client) - krb5_free_principal(gssapi_krb5_context, creds.client); - if (creds.server) - krb5_free_principal(gssapi_krb5_context, creds.server); -} - -/* - * first stage of init-sec-context - */ - -static OM_uint32 -gsskrb5_initiator_start -(OM_uint32 * minor_status, - krb5_ccache ccache, - gss_ctx_id_t * context_handle, - const gss_name_t target_name, - const gss_OID mech_type, - OM_uint32 req_flags, - OM_uint32 time_req, - const gss_channel_bindings_t input_chan_bindings, - const gss_buffer_t input_token, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec - ) -{ - OM_uint32 ret = GSS_S_FAILURE; - krb5_error_code kret; - krb5_flags ap_options; - krb5_creds *cred = NULL; - krb5_data outbuf; - OM_uint32 flags; - krb5_data authenticator; - Checksum cksum; - krb5_enctype enctype; - krb5_data fwd_data; - int is_cfx; - - krb5_data_zero(&outbuf); - krb5_data_zero(&fwd_data); - - (*context_handle)->more_flags |= LOCAL; - - /* We need to get the credentials for the requested target */ - ret = gsskrb5_get_creds(minor_status, - ccache, - context_handle, - target_name, - time_req, - time_rec, - &cred); - if (ret) return ret; - - /* - * We need to setup some compat stuff, this assumes that context_handle->target is already set - */ - ret = _gss_DES3_get_mic_compat(minor_status, *context_handle); - if (ret) return ret; - - /* We need the key and a random local subkey */ - { - kret = krb5_auth_con_setkey(gssapi_krb5_context, - (*context_handle)->auth_context, - &cred->session); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - kret = krb5_auth_con_generatelocalsubkey(gssapi_krb5_context, - (*context_handle)->auth_context, - &cred->session); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - } - - /* We need to prepare the flags used for this context */ - { - flags = 0; - ap_options = 0; - - /* - * The KDC may have issued us a service ticket marked NOT - * ok-as-delegate. We may still wish to force the matter, and to - * allow this we check a per-realm gssapi [appdefaults] config - * option. If ok-as-delegate in the config file is set to TRUE - * (default FALSE) and our caller has so requested, we will still - * attempt to forward the ticket. - * - * Otherwise, strip the GSS_C_DELEG_FLAG (so we don't attempt a - * delegation) - */ - if (!cred->flags.b.ok_as_delegate) { - krb5_boolean delegate; - - krb5_appdefault_boolean(gssapi_krb5_context, - "gssapi", target_name->realm, - "ok-as-delegate", FALSE, &delegate); - if (!delegate) - req_flags &= ~GSS_C_DELEG_FLAG; - } - - if (req_flags & GSS_C_DELEG_FLAG) { - do_delegation((*context_handle)->auth_context, - ccache, cred, target_name, &fwd_data, &flags); - } - - if (req_flags & GSS_C_MUTUAL_FLAG) { - flags |= GSS_C_MUTUAL_FLAG; - ap_options |= AP_OPTS_MUTUAL_REQUIRED; - } - - if (req_flags & GSS_C_REPLAY_FLAG) { - flags |= GSS_C_REPLAY_FLAG; - } - - if (req_flags & GSS_C_SEQUENCE_FLAG) { - flags |= GSS_C_SEQUENCE_FLAG; - } - - if (req_flags & GSS_C_ANON_FLAG) { - ;/* XXX */ - } - - if (req_flags & GSS_C_DCE_STYLE) { - flags |= GSS_C_DCE_STYLE; - /* GSS_C_DCE_STYLE implies GSS_C_MUTUAL_FLAG */ - flags |= GSS_C_MUTUAL_FLAG; - ap_options |= AP_OPTS_MUTUAL_REQUIRED; - } - - if (req_flags & GSS_C_IDENTIFY_FLAG) { - flags |= GSS_C_IDENTIFY_FLAG; - } - - if (req_flags & GSS_C_EXTENDED_ERROR_FLAG) { - flags |= GSS_C_EXTENDED_ERROR_FLAG; - } - - /* TODO: why are this always there? --metze */ - flags |= GSS_C_CONF_FLAG; - flags |= GSS_C_INTEG_FLAG; - flags |= GSS_C_TRANS_FLAG; - - if (ret_flags) *ret_flags = flags; - (*context_handle)->flags = flags; - } - - /* We need to generate the 8003 checksum */ - { - ret = gssapi_krb5_create_8003_checksum(minor_status, - input_chan_bindings, - flags, - &fwd_data, - &cksum); - krb5_data_free (&fwd_data); - if (ret) return ret; - } - - enctype = (*context_handle)->auth_context->keyblock->keytype; - - gsskrb5_is_cfx(*context_handle, &is_cfx); - - if (is_cfx != 0) { - kret = krb5_auth_con_addflags(gssapi_krb5_context, - (*context_handle)->auth_context, - KRB5_AUTH_CONTEXT_USE_SUBKEY, - NULL); - (*context_handle)->more_flags |= ACCEPTOR_SUBKEY; - } - - /* We need to create an Authenticator */ - { - kret = krb5_build_authenticator (gssapi_krb5_context, - (*context_handle)->auth_context, - enctype, - cred, - &cksum, - NULL, - &authenticator, - KRB5_KU_AP_REQ_AUTH); - free_Checksum(&cksum); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - } - - /* We need to create the AP_REQ */ - { - kret = krb5_build_ap_req(gssapi_krb5_context, - enctype, - cred, - ap_options, - authenticator, - &outbuf); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - } - - /* We need to encapsulate the AP_REQ if GSS_C_DCE_STYLE isn't in use */ - { - if (!(flags & GSS_C_DCE_STYLE)) { - ret = gssapi_krb5_encapsulate(minor_status, &outbuf, output_token, - "\x01\x00", GSS_KRB5_MECHANISM); - krb5_data_free (&outbuf); - if (ret) return ret; - } else { - output_token->length = outbuf.length; - output_token->value = outbuf.data; - } - } - - /* We no longer need the creds */ - krb5_free_creds(gssapi_krb5_context, cred); - - /* We are done if GSS_C_MUTUAL_FLAG is in use */ - if (flags & GSS_C_MUTUAL_FLAG) { - (*context_handle)->state = INITIATOR_WAIT_FOR_MUTAL; - return GSS_S_CONTINUE_NEEDED; - } - - return gsskrb5_initiator_ready(minor_status, context_handle); -} - -static OM_uint32 -gsskrb5_initiator_wait_for_mutual( - OM_uint32 * minor_status, - krb5_ccache ccache, - gss_ctx_id_t * context_handle, - const gss_name_t target_name, - const gss_OID mech_type, - OM_uint32 req_flags, - OM_uint32 time_req, - const gss_channel_bindings_t input_chan_bindings, - const gss_buffer_t input_token, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec) -{ - OM_uint32 ret; - krb5_error_code kret; - krb5_data inbuf; - OM_uint32 flags = (*context_handle)->flags; - int32_t l_seq_number; - int32_t r_seq_number; - - /* We need to decapsulate the AP_REP if GSS_C_DCE_STYLE isn't in use */ - { - if (!(flags & GSS_C_DCE_STYLE)) { - ret = gssapi_krb5_decapsulate(minor_status, input_token, &inbuf, - "\x02\x00", GSS_KRB5_MECHANISM); - if (ret) return ret; - } else { - inbuf.length = input_token->length; - inbuf.data = input_token->value; - } - } - - /* We need to verify the AP_REP */ - { - krb5_ap_rep_enc_part *repl; - - kret = krb5_rd_rep(gssapi_krb5_context, - (*context_handle)->auth_context, - &inbuf, - &repl); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - krb5_free_ap_rep_enc_part(gssapi_krb5_context, repl); - } - - /* We need to check the liftime */ - { - OM_uint32 lifetime_rec; - - ret = gssapi_lifetime_left(minor_status, - (*context_handle)->lifetime, - &lifetime_rec); - if (ret) return ret; - - if (lifetime_rec == 0) { - return GSS_S_CONTEXT_EXPIRED; - } - - if (time_rec) *time_rec = lifetime_rec; - } - - /* We need to give the caller the flags which are in use */ - if (ret_flags) *ret_flags = (*context_handle)->flags; - - /* We are done here if GSS_C_DCE_STYLE isn't in use */ - if (!(flags & GSS_C_DCE_STYLE)) { - return gsskrb5_initiator_ready(minor_status, context_handle); - } - - /* - * We need to set the local seq_number to the remote one just for the krb5_mk_rep(), - * and then we need to use the old local seq_number again for the GSS_Wrap() messages - */ - { - kret = krb5_auth_getremoteseqnumber(gssapi_krb5_context, - (*context_handle)->auth_context, - &r_seq_number); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - kret = krb5_auth_con_getlocalseqnumber(gssapi_krb5_context, - (*context_handle)->auth_context, - &l_seq_number); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - kret = krb5_auth_con_setlocalseqnumber(gssapi_krb5_context, - (*context_handle)->auth_context, - r_seq_number); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - } - - /* We need to create an AP_REP */ - { - krb5_data outbuf; - - kret = krb5_mk_rep(gssapi_krb5_context, - (*context_handle)->auth_context, - &outbuf); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - - output_token->length = outbuf.length; - output_token->value = outbuf.data; - } - - /* We need to reset the local seq_number */ - { - kret = krb5_auth_con_setlocalseqnumber(gssapi_krb5_context, - (*context_handle)->auth_context, - l_seq_number); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - } - - return gsskrb5_initiator_ready(minor_status, context_handle); -} - -static OM_uint32 -gsskrb5_init_sec_context - (OM_uint32 * minor_status, - const gss_cred_id_t initiator_cred_handle, - gss_ctx_id_t * context_handle, - const gss_name_t target_name, - const gss_OID mech_type, - OM_uint32 req_flags, - OM_uint32 time_req, - const gss_channel_bindings_t input_chan_bindings, - const gss_buffer_t input_token, - gss_OID * actual_mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec - ) -{ - OM_uint32 ret; - krb5_error_code kret; - krb5_ccache ccache = NULL; - - if (*context_handle == GSS_C_NO_CONTEXT) { - ret = _gsskrb5_create_ctx(minor_status, - context_handle, - input_chan_bindings, - INITIATOR_START); - if (ret) return ret; - } - - if (actual_mech_type) *actual_mech_type = GSS_KRB5_MECHANISM; - - if (initiator_cred_handle == GSS_C_NO_CREDENTIAL) { - kret = krb5_cc_default (gssapi_krb5_context, &ccache); - if (kret) { - gssapi_krb5_set_error_string (); - *minor_status = kret; - return GSS_S_FAILURE; - } - } else { - ccache = initiator_cred_handle->ccache; - } - - HEIMDAL_MUTEX_lock(&(*context_handle)->ctx_id_mutex); - - switch ((*context_handle)->state) { - case INITIATOR_START: - ret = gsskrb5_initiator_start(minor_status, - ccache, - context_handle, - target_name, - mech_type, - req_flags, - time_req, - input_chan_bindings, - input_token, - output_token, - ret_flags, - time_rec); - break; - case INITIATOR_WAIT_FOR_MUTAL: - ret = gsskrb5_initiator_wait_for_mutual(minor_status, - ccache, - context_handle, - target_name, - mech_type, - req_flags, - time_req, - input_chan_bindings, - input_token, - output_token, - ret_flags, - time_rec); - break; - case INITIATOR_READY: - /* should this be GSS_S_BAD_STATUS ? --metze */ - - /* We need to check the liftime */ - { - OM_uint32 lifetime_rec; - - ret = gssapi_lifetime_left(minor_status, - (*context_handle)->lifetime, - &lifetime_rec); - if (ret) break; - - if (lifetime_rec == 0) { - *minor_status = 0; - ret = GSS_S_CONTEXT_EXPIRED; - break; - } - - if (time_rec) *time_rec = lifetime_rec; - } - - /* We need to give the caller the flags which are in use */ - if (ret_flags) *ret_flags = (*context_handle)->flags; - - ret = GSS_S_COMPLETE; - break; - default: - /* TODO: is this correct here? --metze */ - ret = GSS_S_BAD_STATUS; - break; - } - - if (initiator_cred_handle == GSS_C_NO_CREDENTIAL) { - krb5_cc_close(gssapi_krb5_context, ccache); - } - - HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex); - - return ret; -} - -static OM_uint32 -spnego_reply - (OM_uint32 * minor_status, - const gss_cred_id_t initiator_cred_handle, - gss_ctx_id_t * context_handle, - const gss_name_t target_name, - const gss_OID mech_type, - OM_uint32 req_flags, - OM_uint32 time_req, - const gss_channel_bindings_t input_chan_bindings, - const gss_buffer_t input_token, - gss_OID * actual_mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec - ) -{ - OM_uint32 ret; - krb5_data indata; - NegTokenTarg targ; - u_char oidbuf[17]; - size_t oidlen; - gss_buffer_desc sub_token; - ssize_t mech_len; - const u_char *p; - size_t len, taglen; - krb5_boolean require_mic; - - output_token->length = 0; - output_token->value = NULL; - - /* - * SPNEGO doesn't include gss wrapping on SubsequentContextToken - * like the Kerberos 5 mech does. But lets check for it anyway. - */ - - mech_len = gssapi_krb5_get_mech (input_token->value, - input_token->length, - &p); - - if (mech_len < 0) { - indata.data = input_token->value; - indata.length = input_token->length; - } else if (mech_len == GSS_KRB5_MECHANISM->length - && memcmp(GSS_KRB5_MECHANISM->elements, p, mech_len) == 0) - return gsskrb5_init_sec_context (minor_status, - initiator_cred_handle, - context_handle, - target_name, - GSS_KRB5_MECHANISM, - req_flags, - time_req, - input_chan_bindings, - input_token, - actual_mech_type, - output_token, - ret_flags, - time_rec); - else if (mech_len == GSS_SPNEGO_MECHANISM->length - && memcmp(GSS_SPNEGO_MECHANISM->elements, p, mech_len) == 0){ - ret = _gssapi_decapsulate (minor_status, - input_token, - &indata, - GSS_SPNEGO_MECHANISM); - if (ret) - return ret; - } else - return GSS_S_BAD_MECH; - - ret = der_match_tag_and_length((const char *)indata.data, - indata.length, - ASN1_C_CONTEXT, CONS, 1, &len, &taglen); - if (ret) { - gssapi_krb5_set_status("Failed to decode NegToken choice"); - *minor_status = ret; - return GSS_S_FAILURE; - } - - if(len > indata.length - taglen) { - gssapi_krb5_set_status("Buffer overrun in NegToken choice"); - *minor_status = ASN1_OVERRUN; - return GSS_S_FAILURE; - } - - ret = decode_NegTokenTarg((const char *)indata.data + taglen, - len, &targ, NULL); - if (ret) { - gssapi_krb5_set_status("Failed to decode NegTokenTarg"); - *minor_status = ret; - return GSS_S_FAILURE; - } - - if (targ.negResult == NULL - || *(targ.negResult) == reject - || targ.supportedMech == NULL) { - free_NegTokenTarg(&targ); - return GSS_S_BAD_MECH; - } - - ret = der_put_oid(oidbuf + sizeof(oidbuf) - 1, - sizeof(oidbuf), - targ.supportedMech, - &oidlen); - if (ret || oidlen != GSS_KRB5_MECHANISM->length - || memcmp(oidbuf + sizeof(oidbuf) - oidlen, - GSS_KRB5_MECHANISM->elements, - oidlen) != 0) { - free_NegTokenTarg(&targ); - return GSS_S_BAD_MECH; - } - - if (targ.responseToken != NULL) { - sub_token.length = targ.responseToken->length; - sub_token.value = targ.responseToken->data; - } else { - sub_token.length = 0; - sub_token.value = NULL; - } - - ret = gsskrb5_init_sec_context(minor_status, - initiator_cred_handle, - context_handle, - target_name, - GSS_KRB5_MECHANISM, - req_flags, - time_req, - input_chan_bindings, - &sub_token, - actual_mech_type, - output_token, - ret_flags, - time_rec); - if (ret) { - free_NegTokenTarg(&targ); - return ret; - } - - /* - * Verify the mechListMIC if CFX was used; or if local policy - * dictated so. - */ - ret = _gss_spnego_require_mechlist_mic(minor_status, *context_handle, - &require_mic); - if (ret) { - free_NegTokenTarg(&targ); - return ret; - } - - if (require_mic) { - MechTypeList mechlist; - MechType m0; - size_t buf_len; - gss_buffer_desc mic_buf, mech_buf; - - if (targ.mechListMIC == NULL) { - free_NegTokenTarg(&targ); - *minor_status = 0; - return GSS_S_BAD_MIC; - } - - mechlist.len = 1; - mechlist.val = &m0; - - ret = der_get_oid(GSS_KRB5_MECHANISM->elements, - GSS_KRB5_MECHANISM->length, - &m0, - NULL); - if (ret) { - free_NegTokenTarg(&targ); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - ASN1_MALLOC_ENCODE(MechTypeList, mech_buf.value, mech_buf.length, - &mechlist, &buf_len, ret); - if (ret) { - free_NegTokenTarg(&targ); - free_oid(&m0); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - if (mech_buf.length != buf_len) - abort(); - - mic_buf.length = targ.mechListMIC->length; - mic_buf.value = targ.mechListMIC->data; - - ret = gss_verify_mic(minor_status, *context_handle, - &mech_buf, &mic_buf, NULL); - free(mech_buf.value); - free_oid(&m0); - } - free_NegTokenTarg(&targ); - return ret; -} - -static OM_uint32 -spnego_initial - (OM_uint32 * minor_status, - const gss_cred_id_t initiator_cred_handle, - gss_ctx_id_t * context_handle, - const gss_name_t target_name, - const gss_OID mech_type, - OM_uint32 req_flags, - OM_uint32 time_req, - const gss_channel_bindings_t input_chan_bindings, - const gss_buffer_t input_token, - gss_OID * actual_mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec - ) -{ - NegTokenInit ni; - int ret; - OM_uint32 sub, minor; - gss_buffer_desc mech_token; - u_char *buf; - size_t buf_size, buf_len; - krb5_data data; - - memset (&ni, 0, sizeof(ni)); - - ALLOC(ni.mechTypes, 1); - if (ni.mechTypes == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - ALLOC_SEQ(ni.mechTypes, 1); - if (ni.mechTypes->val == NULL) { - free_NegTokenInit(&ni); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - ret = der_get_oid(GSS_KRB5_MECHANISM->elements, - GSS_KRB5_MECHANISM->length, - &ni.mechTypes->val[0], - NULL); - if (ret) { - free_NegTokenInit(&ni); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - -#if 0 - ALLOC(ni.reqFlags, 1); - if (ni.reqFlags == NULL) { - free_NegTokenInit(&ni); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - ni.reqFlags->delegFlag = req_flags & GSS_C_DELEG_FLAG; - ni.reqFlags->mutualFlag = req_flags & GSS_C_MUTUAL_FLAG; - ni.reqFlags->replayFlag = req_flags & GSS_C_REPLAY_FLAG; - ni.reqFlags->sequenceFlag = req_flags & GSS_C_SEQUENCE_FLAG; - ni.reqFlags->anonFlag = req_flags & GSS_C_ANON_FLAG; - ni.reqFlags->confFlag = req_flags & GSS_C_CONF_FLAG; - ni.reqFlags->integFlag = req_flags & GSS_C_INTEG_FLAG; -#else - ni.reqFlags = NULL; -#endif - - sub = gsskrb5_init_sec_context(&minor, - initiator_cred_handle, - context_handle, - target_name, - GSS_KRB5_MECHANISM, - req_flags, - time_req, - input_chan_bindings, - GSS_C_NO_BUFFER, - actual_mech_type, - &mech_token, - ret_flags, - time_rec); - if (GSS_ERROR(sub)) { - free_NegTokenInit(&ni); - return sub; - } - if (mech_token.length != 0) { - ALLOC(ni.mechToken, 1); - if (ni.mechToken == NULL) { - free_NegTokenInit(&ni); - gss_release_buffer(&minor, &mech_token); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - ni.mechToken->length = mech_token.length; - ni.mechToken->data = malloc(mech_token.length); - if (ni.mechToken->data == NULL && mech_token.length != 0) { - free_NegTokenInit(&ni); - gss_release_buffer(&minor, &mech_token); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - memcpy(ni.mechToken->data, mech_token.value, mech_token.length); - gss_release_buffer(&minor, &mech_token); - } else - ni.mechToken = NULL; - - /* XXX ignore mech list mic for now */ - ni.mechListMIC = NULL; - - - { - NegotiationToken nt; - - nt.element = choice_NegotiationToken_negTokenInit; - nt.u.negTokenInit = ni; - - ASN1_MALLOC_ENCODE(NegotiationToken, buf, buf_size, - &nt, &buf_len, ret); - if (ret == 0 && buf_size != buf_len) - abort(); - } - - data.data = buf; - data.length = buf_size; - - free_NegTokenInit(&ni); - if (ret) - return ret; - - sub = _gssapi_encapsulate(minor_status, - &data, - output_token, - GSS_SPNEGO_MECHANISM); - free (buf); - - if (sub) - return sub; - - return GSS_S_CONTINUE_NEEDED; -} - -static OM_uint32 -spnego_init_sec_context - (OM_uint32 * minor_status, - const gss_cred_id_t initiator_cred_handle, - gss_ctx_id_t * context_handle, - const gss_name_t target_name, - const gss_OID mech_type, - OM_uint32 req_flags, - OM_uint32 time_req, - const gss_channel_bindings_t input_chan_bindings, - const gss_buffer_t input_token, - gss_OID * actual_mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec - ) -{ - if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) - return spnego_initial (minor_status, - initiator_cred_handle, - context_handle, - target_name, - mech_type, - req_flags, - time_req, - input_chan_bindings, - input_token, - actual_mech_type, - output_token, - ret_flags, - time_rec); - else - return spnego_reply (minor_status, - initiator_cred_handle, - context_handle, - target_name, - mech_type, - req_flags, - time_req, - input_chan_bindings, - input_token, - actual_mech_type, - output_token, - ret_flags, - time_rec); -} - -/* - * gss_init_sec_context - */ - -OM_uint32 gss_init_sec_context - (OM_uint32 * minor_status, - const gss_cred_id_t initiator_cred_handle, - gss_ctx_id_t * context_handle, - const gss_name_t target_name, - const gss_OID mech_type, - OM_uint32 req_flags, - OM_uint32 time_req, - const gss_channel_bindings_t input_chan_bindings, - const gss_buffer_t input_token, - gss_OID * actual_mech_type, - gss_buffer_t output_token, - OM_uint32 * ret_flags, - OM_uint32 * time_rec - ) -{ - GSSAPI_KRB5_INIT (); - - output_token->length = 0; - output_token->value = NULL; - - if (ret_flags) - *ret_flags = 0; - if (time_rec) - *time_rec = 0; - - if (target_name == GSS_C_NO_NAME) { - if (actual_mech_type) - *actual_mech_type = GSS_C_NO_OID; - *minor_status = 0; - return GSS_S_BAD_NAME; - } - - if (mech_type == GSS_C_NO_OID || - gss_oid_equal(mech_type, GSS_KRB5_MECHANISM)) - return gsskrb5_init_sec_context(minor_status, - initiator_cred_handle, - context_handle, - target_name, - mech_type, - req_flags, - time_req, - input_chan_bindings, - input_token, - actual_mech_type, - output_token, - ret_flags, - time_rec); - else if (gss_oid_equal(mech_type, GSS_SPNEGO_MECHANISM)) - return spnego_init_sec_context (minor_status, - initiator_cred_handle, - context_handle, - target_name, - mech_type, - req_flags, - time_req, - input_chan_bindings, - input_token, - actual_mech_type, - output_token, - ret_flags, - time_rec); - else - return GSS_S_BAD_MECH; -} diff --git a/source4/heimdal/lib/gssapi/inquire_cred.c b/source4/heimdal/lib/gssapi/inquire_cred.c deleted file mode 100644 index 9ed1ff4cc4..0000000000 --- a/source4/heimdal/lib/gssapi/inquire_cred.c +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 1997, 2003 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include "gssapi_locl.h" - -RCSID("$Id: inquire_cred.c,v 1.7 2004/11/30 19:27:11 lha Exp $"); - -OM_uint32 gss_inquire_cred - (OM_uint32 * minor_status, - const gss_cred_id_t cred_handle, - gss_name_t * name, - OM_uint32 * lifetime, - gss_cred_usage_t * cred_usage, - gss_OID_set * mechanisms - ) -{ - gss_cred_id_t cred; - OM_uint32 ret; - - *minor_status = 0; - - if (name) - *name = NULL; - if (mechanisms) - *mechanisms = GSS_C_NO_OID_SET; - - if (cred_handle == GSS_C_NO_CREDENTIAL) { - ret = gss_acquire_cred(minor_status, - GSS_C_NO_NAME, - GSS_C_INDEFINITE, - GSS_C_NO_OID_SET, - GSS_C_BOTH, - &cred, - NULL, - NULL); - if (ret) - return ret; - } else - cred = (gss_cred_id_t)cred_handle; - - HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); - - if (name != NULL) { - if (cred->principal != NULL) { - ret = gss_duplicate_name(minor_status, cred->principal, - name); - if (ret) - goto out; - } else if (cred->usage == GSS_C_ACCEPT) { - *minor_status = krb5_sname_to_principal(gssapi_krb5_context, NULL, - NULL, KRB5_NT_SRV_HST, name); - if (*minor_status) { - ret = GSS_S_FAILURE; - goto out; - } - } else { - *minor_status = krb5_get_default_principal(gssapi_krb5_context, - name); - if (*minor_status) { - ret = GSS_S_FAILURE; - goto out; - } - } - } - if (lifetime != NULL) { - ret = gssapi_lifetime_left(minor_status, - cred->lifetime, - lifetime); - if (ret) - goto out; - } - if (cred_usage != NULL) - *cred_usage = cred->usage; - - if (mechanisms != NULL) { - ret = gss_create_empty_oid_set(minor_status, mechanisms); - if (ret) - goto out; - ret = gss_add_oid_set_member(minor_status, - &cred->mechanisms->elements[0], - mechanisms); - if (ret) - goto out; - } - ret = GSS_S_COMPLETE; - out: - HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); - - if (cred_handle == GSS_C_NO_CREDENTIAL) - ret = gss_release_cred(minor_status, &cred); - - return ret; -} diff --git a/source4/heimdal/lib/gssapi/8003.c b/source4/heimdal/lib/gssapi/krb5/8003.c index 359bb6e715..0123f67e09 100644 --- a/source4/heimdal/lib/gssapi/8003.c +++ b/source4/heimdal/lib/gssapi/krb5/8003.c @@ -31,12 +31,12 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: 8003.c,v 1.18 2006/05/04 11:55:40 lha Exp $"); +RCSID("$Id: 8003.c,v 1.20 2006/10/07 22:13:51 lha Exp $"); krb5_error_code -gssapi_encode_om_uint32(OM_uint32 n, u_char *p) +_gsskrb5_encode_om_uint32(OM_uint32 n, u_char *p) { p[0] = (n >> 0) & 0xFF; p[1] = (n >> 8) & 0xFF; @@ -46,7 +46,7 @@ gssapi_encode_om_uint32(OM_uint32 n, u_char *p) } krb5_error_code -gssapi_encode_be_om_uint32(OM_uint32 n, u_char *p) +_gsskrb5_encode_be_om_uint32(OM_uint32 n, u_char *p) { p[0] = (n >> 24) & 0xFF; p[1] = (n >> 16) & 0xFF; @@ -56,7 +56,7 @@ gssapi_encode_be_om_uint32(OM_uint32 n, u_char *p) } krb5_error_code -gssapi_decode_om_uint32(const void *ptr, OM_uint32 *n) +_gsskrb5_decode_om_uint32(const void *ptr, OM_uint32 *n) { const u_char *p = ptr; *n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); @@ -64,7 +64,7 @@ gssapi_decode_om_uint32(const void *ptr, OM_uint32 *n) } krb5_error_code -gssapi_decode_be_om_uint32(const void *ptr, OM_uint32 *n) +_gsskrb5_decode_be_om_uint32(const void *ptr, OM_uint32 *n) { const u_char *p = ptr; *n = (p[0] <<24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0); @@ -79,23 +79,23 @@ hash_input_chan_bindings (const gss_channel_bindings_t b, MD5_CTX md5; MD5_Init(&md5); - gssapi_encode_om_uint32 (b->initiator_addrtype, num); + _gsskrb5_encode_om_uint32 (b->initiator_addrtype, num); MD5_Update (&md5, num, sizeof(num)); - gssapi_encode_om_uint32 (b->initiator_address.length, num); + _gsskrb5_encode_om_uint32 (b->initiator_address.length, num); MD5_Update (&md5, num, sizeof(num)); if (b->initiator_address.length) MD5_Update (&md5, b->initiator_address.value, b->initiator_address.length); - gssapi_encode_om_uint32 (b->acceptor_addrtype, num); + _gsskrb5_encode_om_uint32 (b->acceptor_addrtype, num); MD5_Update (&md5, num, sizeof(num)); - gssapi_encode_om_uint32 (b->acceptor_address.length, num); + _gsskrb5_encode_om_uint32 (b->acceptor_address.length, num); MD5_Update (&md5, num, sizeof(num)); if (b->acceptor_address.length) MD5_Update (&md5, b->acceptor_address.value, b->acceptor_address.length); - gssapi_encode_om_uint32 (b->application_data.length, num); + _gsskrb5_encode_om_uint32 (b->application_data.length, num); MD5_Update (&md5, num, sizeof(num)); if (b->application_data.length) MD5_Update (&md5, @@ -112,7 +112,7 @@ hash_input_chan_bindings (const gss_channel_bindings_t b, */ OM_uint32 -gssapi_krb5_create_8003_checksum ( +_gsskrb5_create_8003_checksum ( OM_uint32 *minor_status, const gss_channel_bindings_t input_chan_bindings, OM_uint32 flags, @@ -136,7 +136,7 @@ gssapi_krb5_create_8003_checksum ( } p = result->checksum.data; - gssapi_encode_om_uint32 (16, p); + _gsskrb5_encode_om_uint32 (16, p); p += 4; if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS) { memset (p, 0, 16); @@ -144,7 +144,7 @@ gssapi_krb5_create_8003_checksum ( hash_input_chan_bindings (input_chan_bindings, p); } p += 16; - gssapi_encode_om_uint32 (flags, p); + _gsskrb5_encode_om_uint32 (flags, p); p += 4; if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG)) { @@ -167,7 +167,7 @@ gssapi_krb5_create_8003_checksum ( */ OM_uint32 -gssapi_krb5_verify_8003_checksum( +_gsskrb5_verify_8003_checksum( OM_uint32 *minor_status, const gss_channel_bindings_t input_chan_bindings, const Checksum *cksum, @@ -192,7 +192,7 @@ gssapi_krb5_verify_8003_checksum( } p = cksum->checksum.data; - gssapi_decode_om_uint32(p, &length); + _gsskrb5_decode_om_uint32(p, &length); if(length != sizeof(hash)) { *minor_status = 0; return GSS_S_BAD_BINDINGS; @@ -214,7 +214,7 @@ gssapi_krb5_verify_8003_checksum( p += sizeof(hash); - gssapi_decode_om_uint32(p, flags); + _gsskrb5_decode_om_uint32(p, flags); p += 4; if (cksum->checksum.length > 24 && (*flags & GSS_C_DELEG_FLAG)) { diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c new file mode 100644 index 0000000000..e42bb11b85 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c @@ -0,0 +1,774 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: accept_sec_context.c,v 1.64 2006/10/25 04:19:45 lha Exp $"); + +HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER; +krb5_keytab _gsskrb5_keytab; + +OM_uint32 +_gsskrb5_register_acceptor_identity (const char *identity) +{ + krb5_error_code ret; + + ret = _gsskrb5_init(); + if(ret) + return GSS_S_FAILURE; + + HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); + + if(_gsskrb5_keytab != NULL) { + krb5_kt_close(_gsskrb5_context, _gsskrb5_keytab); + _gsskrb5_keytab = NULL; + } + if (identity == NULL) { + ret = krb5_kt_default(_gsskrb5_context, &_gsskrb5_keytab); + } else { + char *p; + + asprintf(&p, "FILE:%s", identity); + if(p == NULL) { + HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); + return GSS_S_FAILURE; + } + ret = krb5_kt_resolve(_gsskrb5_context, p, &_gsskrb5_keytab); + free(p); + } + HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); + if(ret) + return GSS_S_FAILURE; + return GSS_S_COMPLETE; +} + +void +_gsskrb5i_is_cfx(gsskrb5_ctx ctx, int *is_cfx) +{ + krb5_keyblock *key; + int acceptor = (ctx->more_flags & LOCAL) == 0; + + *is_cfx = 0; + + if (acceptor) { + if (ctx->auth_context->local_subkey) + key = ctx->auth_context->local_subkey; + else + key = ctx->auth_context->remote_subkey; + } else { + if (ctx->auth_context->remote_subkey) + key = ctx->auth_context->remote_subkey; + else + key = ctx->auth_context->local_subkey; + } + if (key == NULL) + key = ctx->auth_context->keyblock; + + if (key == NULL) + return; + + switch (key->keytype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + case ETYPE_DES3_CBC_MD5: + case ETYPE_DES3_CBC_SHA1: + case ETYPE_ARCFOUR_HMAC_MD5: + case ETYPE_ARCFOUR_HMAC_MD5_56: + break; + default : + *is_cfx = 1; + if ((acceptor && ctx->auth_context->local_subkey) || + (!acceptor && ctx->auth_context->remote_subkey)) + ctx->more_flags |= ACCEPTOR_SUBKEY; + break; + } +} + + +static OM_uint32 +gsskrb5_accept_delegated_token +(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + gss_cred_id_t * delegated_cred_handle + ) +{ + krb5_ccache ccache = NULL; + krb5_error_code kret; + int32_t ac_flags, ret = GSS_S_COMPLETE; + + *minor_status = 0; + + /* XXX Create a new delegated_cred_handle? */ + if (delegated_cred_handle == NULL) { + kret = krb5_cc_default (_gsskrb5_context, &ccache); + } else { + *delegated_cred_handle = NULL; + kret = krb5_cc_gen_new (_gsskrb5_context, &krb5_mcc_ops, &ccache); + } + if (kret) { + ctx->flags &= ~GSS_C_DELEG_FLAG; + goto out; + } + + kret = krb5_cc_initialize(_gsskrb5_context, ccache, ctx->source); + if (kret) { + ctx->flags &= ~GSS_C_DELEG_FLAG; + goto out; + } + + krb5_auth_con_removeflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_TIME, + &ac_flags); + kret = krb5_rd_cred2(_gsskrb5_context, + ctx->auth_context, + ccache, + &ctx->fwd_data); + if (kret) + _gsskrb5_set_error_string(); + krb5_auth_con_setflags(_gsskrb5_context, + ctx->auth_context, + ac_flags); + if (kret) { + ctx->flags &= ~GSS_C_DELEG_FLAG; + ret = GSS_S_FAILURE; + *minor_status = kret; + goto out; + } + + if (delegated_cred_handle) { + gsskrb5_cred handle; + + ret = _gsskrb5_import_cred(minor_status, + ccache, + NULL, + NULL, + delegated_cred_handle); + if (ret != GSS_S_COMPLETE) + goto out; + + handle = (gsskrb5_cred) *delegated_cred_handle; + + handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; + krb5_cc_close(_gsskrb5_context, ccache); + ccache = NULL; + } + +out: + if (ccache) { + if (delegated_cred_handle == NULL) + krb5_cc_close(_gsskrb5_context, ccache); + else + krb5_cc_destroy(_gsskrb5_context, ccache); + } + return ret; +} + +static OM_uint32 +gsskrb5_acceptor_ready(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + gss_cred_id_t *delegated_cred_handle) +{ + OM_uint32 ret; + int32_t seq_number; + int is_cfx = 0; + + krb5_auth_getremoteseqnumber (_gsskrb5_context, + ctx->auth_context, + &seq_number); + + _gsskrb5i_is_cfx(ctx, &is_cfx); + + ret = _gssapi_msg_order_create(minor_status, + &ctx->order, + _gssapi_msg_order_f(ctx->flags), + seq_number, 0, is_cfx); + if (ret) + return ret; + + /* + * If requested, set local sequence num to remote sequence if this + * isn't a mutual authentication context + */ + if (!(ctx->flags & GSS_C_MUTUAL_FLAG) && _gssapi_msg_order_f(ctx->flags)) { + krb5_auth_con_setlocalseqnumber(_gsskrb5_context, + ctx->auth_context, + seq_number); + } + + /* + * We should handle the delegation ticket, in case it's there + */ + if (ctx->fwd_data.length > 0 && (ctx->flags & GSS_C_DELEG_FLAG)) { + ret = gsskrb5_accept_delegated_token(minor_status, + ctx, + delegated_cred_handle); + if (ret) + return ret; + } else { + /* Well, looks like it wasn't there after all */ + ctx->flags &= ~GSS_C_DELEG_FLAG; + } + + ctx->state = ACCEPTOR_READY; + ctx->more_flags |= OPEN; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +gsskrb5_acceptor_start(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle) +{ + krb5_error_code kret; + OM_uint32 ret = GSS_S_COMPLETE; + krb5_data indata; + krb5_flags ap_options; + krb5_ticket *ticket = NULL; + krb5_keytab keytab = NULL; + krb5_keyblock *keyblock = NULL; + int is_cfx = 0; + const gsskrb5_cred acceptor_cred = (gsskrb5_cred)acceptor_cred_handle; + + /* + * We may, or may not, have an escapsulation. + */ + ret = _gsskrb5_decapsulate (minor_status, + input_token_buffer, + &indata, + "\x01\x00", + GSS_KRB5_MECHANISM); + + if (ret) { + /* Assume that there is no OID wrapping. */ + indata.length = input_token_buffer->length; + indata.data = input_token_buffer->value; + } + + /* + * We need to get our keytab + */ + if (acceptor_cred == NULL) { + if (_gsskrb5_keytab != NULL) + keytab = _gsskrb5_keytab; + } else if (acceptor_cred->keytab != NULL) { + keytab = acceptor_cred->keytab; + } + + /* + * We need to check the ticket and create the AP-REP packet + */ + kret = krb5_rd_req_return_keyblock(_gsskrb5_context, + &ctx->auth_context, + &indata, + (acceptor_cred == NULL) ? NULL : acceptor_cred->principal, + keytab, + &ap_options, + &ticket, + &keyblock); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + + /* + * We need to remember some data on the context_handle. + */ + ctx->ticket = ticket; + ctx->service_keyblock = keyblock; + ctx->lifetime = ticket->ticket.endtime; + + /* + * We need to copy the principal names to the context and the + * calling layer. + */ + kret = krb5_copy_principal(_gsskrb5_context, + ticket->client, + &ctx->source); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + } + + kret = krb5_copy_principal(_gsskrb5_context, ticket->server, &ctx->target); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + + /* + * We need to setup some compat stuff, this assumes that + * context_handle->target is already set. + */ + ret = _gss_DES3_get_mic_compat(minor_status, ctx); + if (ret) + return ret; + + if (src_name != NULL) { + kret = krb5_copy_principal (_gsskrb5_context, + ticket->client, + (gsskrb5_name*)src_name); + if (kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + } + + /* + * We need to get the flags out of the 8003 checksum. + */ + { + krb5_authenticator authenticator; + + kret = krb5_auth_con_getauthenticator(_gsskrb5_context, + ctx->auth_context, + &authenticator); + if(kret) { + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + + if (authenticator->cksum->cksumtype == CKSUMTYPE_GSSAPI) { + ret = _gsskrb5_verify_8003_checksum(minor_status, + input_chan_bindings, + authenticator->cksum, + &ctx->flags, + &ctx->fwd_data); + + krb5_free_authenticator(_gsskrb5_context, &authenticator); + if (ret) { + return ret; + } + } else { + krb5_crypto crypto; + + kret = krb5_crypto_init(_gsskrb5_context, + ctx->auth_context->keyblock, + 0, &crypto); + if(kret) { + krb5_free_authenticator(_gsskrb5_context, &authenticator); + + ret = GSS_S_FAILURE; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + + /* + * Windows accepts Samba3's use of a kerberos, rather than + * GSSAPI checksum here + */ + + kret = krb5_verify_checksum(_gsskrb5_context, + crypto, KRB5_KU_AP_REQ_AUTH_CKSUM, NULL, 0, + authenticator->cksum); + krb5_free_authenticator(_gsskrb5_context, &authenticator); + krb5_crypto_destroy(_gsskrb5_context, crypto); + + if(kret) { + ret = GSS_S_BAD_SIG; + *minor_status = kret; + _gsskrb5_set_error_string (); + return ret; + } + + /* + * Samba style get some flags (but not DCE-STYLE) + */ + ctx->flags = + GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG; + } + } + + if(ctx->flags & GSS_C_MUTUAL_FLAG) { + krb5_data outbuf; + + _gsskrb5i_is_cfx(ctx, &is_cfx); + + if (is_cfx != 0 + || (ap_options & AP_OPTS_USE_SUBKEY)) { + kret = krb5_auth_con_addflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_USE_SUBKEY, + NULL); + ctx->more_flags |= ACCEPTOR_SUBKEY; + } + + kret = krb5_mk_rep(_gsskrb5_context, + ctx->auth_context, + &outbuf); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } + + if (ctx->flags & GSS_C_DCE_STYLE) { + output_token->length = outbuf.length; + output_token->value = outbuf.data; + } else { + ret = _gsskrb5_encapsulate(minor_status, + &outbuf, + output_token, + "\x02\x00", + GSS_KRB5_MECHANISM); + krb5_data_free (&outbuf); + if (ret) + return ret; + } + } + + ctx->flags |= GSS_C_TRANS_FLAG; + + /* Remember the flags */ + + ctx->lifetime = ticket->ticket.endtime; + ctx->more_flags |= OPEN; + + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (time_rec) { + ret = _gsskrb5_lifetime_left(minor_status, + ctx->lifetime, + time_rec); + if (ret) { + return ret; + } + } + + /* + * When GSS_C_DCE_STYLE is in use, we need ask for a AP-REP from + * the client. + */ + if (ctx->flags & GSS_C_DCE_STYLE) { + /* + * Return flags to caller, but we haven't processed + * delgations yet + */ + if (ret_flags) + *ret_flags = (ctx->flags & ~GSS_C_DELEG_FLAG); + + ctx->state = ACCEPTOR_WAIT_FOR_DCESTYLE; + return GSS_S_CONTINUE_NEEDED; + } + + ret = gsskrb5_acceptor_ready(minor_status, ctx, delegated_cred_handle); + + if (ret_flags) + *ret_flags = ctx->flags; + + return ret; +} + +static OM_uint32 +acceptor_wait_for_dcestyle(OM_uint32 * minor_status, + gsskrb5_ctx ctx, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_data inbuf; + int32_t r_seq_number, l_seq_number; + + /* + * We know it's GSS_C_DCE_STYLE so we don't need to decapsulate the AP_REP + */ + + inbuf.length = input_token_buffer->length; + inbuf.data = input_token_buffer->value; + + /* + * We need to remeber the old remote seq_number, then check if the + * client has replied with our local seq_number, and then reset + * the remote seq_number to the old value + */ + { + kret = krb5_auth_con_getlocalseqnumber(_gsskrb5_context, + ctx->auth_context, + &l_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_auth_getremoteseqnumber(_gsskrb5_context, + ctx->auth_context, + &r_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_auth_con_setremoteseqnumber(_gsskrb5_context, + ctx->auth_context, + l_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + } + + /* + * We need to verify the AP_REP, but we need to flag that this is + * DCE_STYLE, so don't check the timestamps this time, but put the + * flag DO_TIME back afterward. + */ + { + krb5_ap_rep_enc_part *repl; + int32_t auth_flags; + + krb5_auth_con_removeflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_TIME, + &auth_flags); + + kret = krb5_rd_rep(_gsskrb5_context, ctx->auth_context, &inbuf, &repl); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + krb5_free_ap_rep_enc_part(_gsskrb5_context, repl); + krb5_auth_con_setflags(_gsskrb5_context, ctx->auth_context, auth_flags); + } + + /* We need to check the liftime */ + { + OM_uint32 lifetime_rec; + + ret = _gsskrb5_lifetime_left(minor_status, + ctx->lifetime, + &lifetime_rec); + if (ret) { + return ret; + } + if (lifetime_rec == 0) { + return GSS_S_CONTEXT_EXPIRED; + } + + if (time_rec) *time_rec = lifetime_rec; + } + + /* We need to give the caller the flags which are in use */ + if (ret_flags) *ret_flags = ctx->flags; + + if (src_name) { + kret = krb5_copy_principal(_gsskrb5_context, + ctx->source, + (gsskrb5_name*)src_name); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } + } + + /* + * After the krb5_rd_rep() the remote and local seq_number should + * be the same, because the client just replies the seq_number + * from our AP-REP in its AP-REP, but then the client uses the + * seq_number from its AP-REQ for GSS_wrap() + */ + { + int32_t tmp_r_seq_number, tmp_l_seq_number; + + kret = krb5_auth_getremoteseqnumber(_gsskrb5_context, + ctx->auth_context, + &tmp_r_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_auth_con_getlocalseqnumber(_gsskrb5_context, + ctx->auth_context, + &tmp_l_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + /* + * Here we check if the client has responsed with our local seq_number, + */ + if (tmp_r_seq_number != tmp_l_seq_number) { + return GSS_S_UNSEQ_TOKEN; + } + } + + /* + * We need to reset the remote seq_number, because the client will use, + * the old one for the GSS_wrap() calls + */ + { + kret = krb5_auth_con_setremoteseqnumber(_gsskrb5_context, + ctx->auth_context, + r_seq_number); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + } + + return gsskrb5_acceptor_ready(minor_status, ctx, delegated_cred_handle); +} + + +OM_uint32 +_gsskrb5_accept_sec_context(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle) +{ + OM_uint32 ret; + gsskrb5_ctx ctx; + + GSSAPI_KRB5_INIT(); + + output_token->length = 0; + output_token->value = NULL; + + if (src_name != NULL) + *src_name = NULL; + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (*context_handle == GSS_C_NO_CONTEXT) { + ret = _gsskrb5_create_ctx(minor_status, + context_handle, + input_chan_bindings, + ACCEPTOR_START); + if (ret) + return ret; + } + + ctx = (gsskrb5_ctx)*context_handle; + + + /* + * TODO: check the channel_bindings + * (above just sets them to krb5 layer) + */ + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + switch (ctx->state) { + case ACCEPTOR_START: + ret = gsskrb5_acceptor_start(minor_status, + ctx, + acceptor_cred_handle, + input_token_buffer, + input_chan_bindings, + src_name, + mech_type, + output_token, + ret_flags, + time_rec, + delegated_cred_handle); + break; + case ACCEPTOR_WAIT_FOR_DCESTYLE: + ret = acceptor_wait_for_dcestyle(minor_status, + ctx, + acceptor_cred_handle, + input_token_buffer, + input_chan_bindings, + src_name, + mech_type, + output_token, + ret_flags, + time_rec, + delegated_cred_handle); + break; + case ACCEPTOR_READY: + /* + * If we get there, the caller have called + * gss_accept_sec_context() one time too many. + */ + ret = GSS_S_BAD_STATUS; + break; + default: + /* TODO: is this correct here? --metze */ + ret = GSS_S_BAD_STATUS; + break; + } + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + if (GSS_ERROR(ret)) { + OM_uint32 min2; + _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER); + } + + return ret; +} diff --git a/source4/heimdal/lib/gssapi/acquire_cred.c b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c index fa5d709a30..df6e137402 100644 --- a/source4/heimdal/lib/gssapi/acquire_cred.c +++ b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,12 +31,12 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: acquire_cred.c,v 1.27 2005/12/01 16:26:02 lha Exp $"); +RCSID("$Id: acquire_cred.c,v 1.31 2006/10/07 22:13:55 lha Exp $"); OM_uint32 -_gssapi_krb5_ccache_lifetime(OM_uint32 *minor_status, +__gsskrb5_ccache_lifetime(OM_uint32 *minor_status, krb5_ccache id, krb5_principal principal, OM_uint32 *lifetime) @@ -48,32 +48,32 @@ _gssapi_krb5_ccache_lifetime(OM_uint32 *minor_status, memset(&in_cred, 0, sizeof(in_cred)); in_cred.client = principal; - realm = krb5_principal_get_realm(gssapi_krb5_context, principal); + realm = krb5_principal_get_realm(_gsskrb5_context, principal); if (realm == NULL) { - gssapi_krb5_clear_status (); + _gsskrb5_clear_status (); *minor_status = KRB5_PRINC_NOMATCH; /* XXX */ return GSS_S_FAILURE; } - kret = krb5_make_principal(gssapi_krb5_context, &in_cred.server, + kret = krb5_make_principal(_gsskrb5_context, &in_cred.server, realm, KRB5_TGS_NAME, realm, NULL); if (kret) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = kret; return GSS_S_FAILURE; } - kret = krb5_get_credentials(gssapi_krb5_context, 0, + kret = krb5_get_credentials(_gsskrb5_context, 0, id, &in_cred, &out_cred); - krb5_free_principal(gssapi_krb5_context, in_cred.server); + krb5_free_principal(_gsskrb5_context, in_cred.server); if (kret) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = kret; return GSS_S_FAILURE; } *lifetime = out_cred->times.endtime; - krb5_free_creds(gssapi_krb5_context, out_cred); + krb5_free_creds(_gsskrb5_context, out_cred); return GSS_S_COMPLETE; } @@ -82,21 +82,21 @@ _gssapi_krb5_ccache_lifetime(OM_uint32 *minor_status, static krb5_error_code -get_keytab(krb5_context context, krb5_keytab *keytab) +get_keytab(krb5_keytab *keytab) { char kt_name[256]; krb5_error_code kret; HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); - if (gssapi_krb5_keytab != NULL) { - kret = krb5_kt_get_name(context, - gssapi_krb5_keytab, + if (_gsskrb5_keytab != NULL) { + kret = krb5_kt_get_name(_gsskrb5_context, + _gsskrb5_keytab, kt_name, sizeof(kt_name)); if (kret == 0) - kret = krb5_kt_resolve(context, kt_name, keytab); + kret = krb5_kt_resolve(_gsskrb5_context, kt_name, keytab); } else - kret = krb5_kt_default(context, keytab); + kret = krb5_kt_default(_gsskrb5_context, keytab); HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); @@ -105,12 +105,11 @@ get_keytab(krb5_context context, krb5_keytab *keytab) static OM_uint32 acquire_initiator_cred (OM_uint32 * minor_status, - krb5_context context, const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, - gss_cred_id_t handle, + gsskrb5_cred handle, gss_OID_set * actual_mechs, OM_uint32 * time_rec ) @@ -120,9 +119,10 @@ static OM_uint32 acquire_initiator_cred krb5_principal def_princ; krb5_get_init_creds_opt *opt; krb5_ccache ccache; - krb5_error_code kret; krb5_keytab keytab; + krb5_error_code kret; + keytab = NULL; ccache = NULL; def_princ = NULL; ret = GSS_S_FAILURE; @@ -132,33 +132,33 @@ static OM_uint32 acquire_initiator_cred * caches, otherwise, fall back to default cache. Ignore * errors. */ if (handle->principal) - kret = krb5_cc_cache_match (gssapi_krb5_context, + kret = krb5_cc_cache_match (_gsskrb5_context, handle->principal, NULL, &ccache); if (ccache == NULL) { - kret = krb5_cc_default(gssapi_krb5_context, &ccache); + kret = krb5_cc_default(_gsskrb5_context, &ccache); if (kret) goto end; } - kret = krb5_cc_get_principal(context, ccache, + kret = krb5_cc_get_principal(_gsskrb5_context, ccache, &def_princ); if (kret != 0) { /* we'll try to use a keytab below */ - krb5_cc_destroy(context, ccache); + krb5_cc_destroy(_gsskrb5_context, ccache); ccache = NULL; kret = 0; } else if (handle->principal == NULL) { - kret = krb5_copy_principal(context, def_princ, + kret = krb5_copy_principal(_gsskrb5_context, def_princ, &handle->principal); if (kret) goto end; } else if (handle->principal != NULL && - krb5_principal_compare(context, handle->principal, + krb5_principal_compare(_gsskrb5_context, handle->principal, def_princ) == FALSE) { /* Before failing, lets check the keytab */ - krb5_free_principal(context, def_princ); + krb5_free_principal(_gsskrb5_context, def_princ); def_princ = NULL; } if (def_princ == NULL) { @@ -166,37 +166,37 @@ static OM_uint32 acquire_initiator_cred * so attempt to get a TGT using a keytab. */ if (handle->principal == NULL) { - kret = krb5_get_default_principal(context, + kret = krb5_get_default_principal(_gsskrb5_context, &handle->principal); if (kret) goto end; } - kret = get_keytab(context, &keytab); + kret = get_keytab(&keytab); if (kret) goto end; - kret = krb5_get_init_creds_opt_alloc(gssapi_krb5_context, &opt); + kret = krb5_get_init_creds_opt_alloc(_gsskrb5_context, &opt); if (kret) goto end; - kret = krb5_get_init_creds_keytab(gssapi_krb5_context, &cred, + kret = krb5_get_init_creds_keytab(_gsskrb5_context, &cred, handle->principal, keytab, 0, NULL, opt); krb5_get_init_creds_opt_free(opt); if (kret) goto end; - kret = krb5_cc_gen_new(gssapi_krb5_context, &krb5_mcc_ops, + kret = krb5_cc_gen_new(_gsskrb5_context, &krb5_mcc_ops, &ccache); if (kret) goto end; - kret = krb5_cc_initialize(gssapi_krb5_context, ccache, cred.client); + kret = krb5_cc_initialize(_gsskrb5_context, ccache, cred.client); if (kret) goto end; - kret = krb5_cc_store_cred(gssapi_krb5_context, ccache, &cred); + kret = krb5_cc_store_cred(_gsskrb5_context, ccache, &cred); if (kret) goto end; handle->lifetime = cred.times.endtime; handle->cred_flags |= GSS_CF_DESTROY_CRED_ON_RELEASE; } else { - ret = _gssapi_krb5_ccache_lifetime(minor_status, + ret = __gsskrb5_ccache_lifetime(minor_status, ccache, handle->principal, &handle->lifetime); @@ -210,17 +210,17 @@ static OM_uint32 acquire_initiator_cred end: if (cred.client != NULL) - krb5_free_cred_contents(context, &cred); + krb5_free_cred_contents(_gsskrb5_context, &cred); if (def_princ != NULL) - krb5_free_principal(context, def_princ); + krb5_free_principal(_gsskrb5_context, def_princ); if (keytab != NULL) - krb5_kt_close(context, keytab); + krb5_kt_close(_gsskrb5_context, keytab); if (ret != GSS_S_COMPLETE) { if (ccache != NULL) - krb5_cc_close(gssapi_krb5_context, ccache); + krb5_cc_close(_gsskrb5_context, ccache); if (kret != 0) { *minor_status = kret; - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); } } return (ret); @@ -228,11 +228,11 @@ end: static OM_uint32 acquire_acceptor_cred (OM_uint32 * minor_status, - krb5_context context, + const gss_name_t desired_name, OM_uint32 time_req, const gss_OID_set desired_mechs, gss_cred_usage_t cred_usage, - gss_cred_id_t handle, + gsskrb5_cred handle, gss_OID_set * actual_mechs, OM_uint32 * time_rec ) @@ -242,7 +242,7 @@ static OM_uint32 acquire_acceptor_cred kret = 0; ret = GSS_S_FAILURE; - kret = get_keytab(context, &handle->keytab); + kret = get_keytab(&handle->keytab); if (kret) goto end; @@ -250,37 +250,38 @@ static OM_uint32 acquire_acceptor_cred if (handle->principal) { krb5_keytab_entry entry; - kret = krb5_kt_get_entry(gssapi_krb5_context, handle->keytab, + kret = krb5_kt_get_entry(_gsskrb5_context, handle->keytab, handle->principal, 0, 0, &entry); if (kret) goto end; - krb5_kt_free_entry(gssapi_krb5_context, &entry); + krb5_kt_free_entry(_gsskrb5_context, &entry); } ret = GSS_S_COMPLETE; end: if (ret != GSS_S_COMPLETE) { - krb5_kt_close(context, handle->keytab); + if (handle->keytab != NULL) + krb5_kt_close(_gsskrb5_context, handle->keytab); if (kret != 0) { *minor_status = kret; - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); } } return (ret); } -OM_uint32 gss_acquire_cred - (OM_uint32 * minor_status, - const gss_name_t desired_name, - OM_uint32 time_req, - const gss_OID_set desired_mechs, - gss_cred_usage_t cred_usage, - gss_cred_id_t * output_cred_handle, - gss_OID_set * actual_mechs, - OM_uint32 * time_rec - ) +OM_uint32 _gsskrb5_acquire_cred +(OM_uint32 * minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * time_rec + ) { - gss_cred_id_t handle; + gsskrb5_cred handle; OM_uint32 ret; if (cred_usage != GSS_C_ACCEPT && cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) { @@ -299,8 +300,8 @@ OM_uint32 gss_acquire_cred if (desired_mechs) { int present = 0; - ret = gss_test_oid_set_member(minor_status, GSS_KRB5_MECHANISM, - desired_mechs, &present); + ret = _gsskrb5_test_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + desired_mechs, &present); if (ret) return ret; if (!present) { @@ -309,66 +310,63 @@ OM_uint32 gss_acquire_cred } } - handle = (gss_cred_id_t)malloc(sizeof(*handle)); - if (handle == GSS_C_NO_CREDENTIAL) { + handle = calloc(1, sizeof(*handle)); + if (handle == NULL) { *minor_status = ENOMEM; return (GSS_S_FAILURE); } - memset(handle, 0, sizeof (*handle)); HEIMDAL_MUTEX_init(&handle->cred_id_mutex); if (desired_name != GSS_C_NO_NAME) { - ret = gss_duplicate_name(minor_status, desired_name, - &handle->principal); - if (ret != GSS_S_COMPLETE) { + krb5_principal name = (krb5_principal)desired_name; + ret = krb5_copy_principal(_gsskrb5_context, name, &handle->principal); + if (ret) { HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); + _gsskrb5_set_error_string(); + *minor_status = ret; free(handle); - return (ret); + return GSS_S_FAILURE; } } if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) { - ret = acquire_initiator_cred(minor_status, gssapi_krb5_context, - desired_name, time_req, - desired_mechs, cred_usage, - handle, actual_mechs, time_rec); + ret = acquire_initiator_cred(minor_status, desired_name, time_req, + desired_mechs, cred_usage, handle, actual_mechs, time_rec); if (ret != GSS_S_COMPLETE) { HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); - krb5_free_principal(gssapi_krb5_context, handle->principal); + krb5_free_principal(_gsskrb5_context, handle->principal); free(handle); return (ret); } } if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) { - ret = acquire_acceptor_cred(minor_status, gssapi_krb5_context, - time_req, - desired_mechs, cred_usage, - handle, actual_mechs, time_rec); + ret = acquire_acceptor_cred(minor_status, desired_name, time_req, + desired_mechs, cred_usage, handle, actual_mechs, time_rec); if (ret != GSS_S_COMPLETE) { HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); - krb5_free_principal(gssapi_krb5_context, handle->principal); + krb5_free_principal(_gsskrb5_context, handle->principal); free(handle); return (ret); } } - ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); + ret = _gsskrb5_create_empty_oid_set(minor_status, &handle->mechanisms); if (ret == GSS_S_COMPLETE) - ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, - &handle->mechanisms); + ret = _gsskrb5_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + &handle->mechanisms); if (ret == GSS_S_COMPLETE) - ret = gss_inquire_cred(minor_status, handle, NULL, time_rec, NULL, - actual_mechs); + ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)handle, + NULL, time_rec, NULL, actual_mechs); if (ret != GSS_S_COMPLETE) { if (handle->mechanisms != NULL) - gss_release_oid_set(NULL, &handle->mechanisms); + _gsskrb5_release_oid_set(NULL, &handle->mechanisms); HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); - krb5_free_principal(gssapi_krb5_context, handle->principal); + krb5_free_principal(_gsskrb5_context, handle->principal); free(handle); return (ret); } *minor_status = 0; if (time_rec) { - ret = gssapi_lifetime_left(minor_status, + ret = _gsskrb5_lifetime_left(minor_status, handle->lifetime, time_rec); @@ -376,8 +374,6 @@ OM_uint32 gss_acquire_cred return ret; } handle->usage = cred_usage; - - *output_cred_handle = handle; + *output_cred_handle = (gss_cred_id_t)handle; return (GSS_S_COMPLETE); } - diff --git a/source4/heimdal/lib/gssapi/krb5/add_cred.c b/source4/heimdal/lib/gssapi/krb5/add_cred.c new file mode 100644 index 0000000000..4892e84798 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/add_cred.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: add_cred.c,v 1.9 2006/10/07 22:13:58 lha Exp $"); + +OM_uint32 _gsskrb5_add_cred ( + OM_uint32 *minor_status, + const gss_cred_id_t input_cred_handle, + const gss_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + OM_uint32 ret, lifetime; + gsskrb5_cred cred, handle; + krb5_const_principal dname; + + handle = NULL; + cred = (gsskrb5_cred)input_cred_handle; + dname = (krb5_const_principal)desired_name; + + if (gss_oid_equal(desired_mech, GSS_KRB5_MECHANISM) == 0) { + *minor_status = 0; + return GSS_S_BAD_MECH; + } + + if (cred == NULL && output_cred_handle == NULL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + + if (cred == NULL) { /* XXX standard conformance failure */ + *minor_status = 0; + return GSS_S_NO_CRED; + } + + /* check if requested output usage is compatible with output usage */ + if (output_cred_handle != NULL) { + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + if (cred->usage != cred_usage && cred->usage != GSS_C_BOTH) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return(GSS_S_FAILURE); + } + } + + /* check that we have the same name */ + if (dname != NULL && + krb5_principal_compare(_gsskrb5_context, dname, + cred->principal) != FALSE) { + if (output_cred_handle) + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = 0; + return GSS_S_BAD_NAME; + } + + /* make a copy */ + if (output_cred_handle) { + krb5_error_code kret; + + handle = calloc(1, sizeof(*handle)); + if (handle == NULL) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + handle->usage = cred_usage; + handle->lifetime = cred->lifetime; + handle->principal = NULL; + handle->keytab = NULL; + handle->ccache = NULL; + handle->mechanisms = NULL; + HEIMDAL_MUTEX_init(&handle->cred_id_mutex); + + ret = GSS_S_FAILURE; + + kret = krb5_copy_principal(_gsskrb5_context, cred->principal, + &handle->principal); + if (kret) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + free(handle); + *minor_status = kret; + return GSS_S_FAILURE; + } + + if (cred->keytab) { + char name[KRB5_KT_PREFIX_MAX_LEN + MAXPATHLEN]; + int len; + + ret = GSS_S_FAILURE; + + kret = krb5_kt_get_type(_gsskrb5_context, cred->keytab, + name, KRB5_KT_PREFIX_MAX_LEN); + if (kret) { + *minor_status = kret; + goto failure; + } + len = strlen(name); + name[len++] = ':'; + + kret = krb5_kt_get_name(_gsskrb5_context, cred->keytab, + name + len, + sizeof(name) - len); + if (kret) { + *minor_status = kret; + goto failure; + } + + kret = krb5_kt_resolve(_gsskrb5_context, name, + &handle->keytab); + if (kret){ + *minor_status = kret; + goto failure; + } + } + + if (cred->ccache) { + const char *type, *name; + char *type_name; + + ret = GSS_S_FAILURE; + + type = krb5_cc_get_type(_gsskrb5_context, cred->ccache); + if (type == NULL){ + *minor_status = ENOMEM; + goto failure; + } + + if (strcmp(type, "MEMORY") == 0) { + ret = krb5_cc_gen_new(_gsskrb5_context, &krb5_mcc_ops, + &handle->ccache); + if (ret) { + *minor_status = ret; + goto failure; + } + + ret = krb5_cc_copy_cache(_gsskrb5_context, cred->ccache, + handle->ccache); + if (ret) { + *minor_status = ret; + goto failure; + } + + } else { + name = krb5_cc_get_name(_gsskrb5_context, cred->ccache); + if (name == NULL) { + *minor_status = ENOMEM; + goto failure; + } + + asprintf(&type_name, "%s:%s", type, name); + if (type_name == NULL) { + *minor_status = ENOMEM; + goto failure; + } + + kret = krb5_cc_resolve(_gsskrb5_context, type_name, + &handle->ccache); + free(type_name); + if (kret) { + *minor_status = kret; + goto failure; + } + } + } + ret = _gsskrb5_create_empty_oid_set(minor_status, &handle->mechanisms); + if (ret) + goto failure; + + ret = _gsskrb5_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + &handle->mechanisms); + if (ret) + goto failure; + } + + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + + ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)cred, + NULL, &lifetime, NULL, actual_mechs); + if (ret) + goto failure; + + if (initiator_time_rec) + *initiator_time_rec = lifetime; + if (acceptor_time_rec) + *acceptor_time_rec = lifetime; + + if (output_cred_handle) { + *output_cred_handle = (gss_cred_id_t)handle; + } + + *minor_status = 0; + return ret; + + failure: + + if (handle) { + if (handle->principal) + krb5_free_principal(_gsskrb5_context, handle->principal); + if (handle->keytab) + krb5_kt_close(_gsskrb5_context, handle->keytab); + if (handle->ccache) + krb5_cc_destroy(_gsskrb5_context, handle->ccache); + if (handle->mechanisms) + _gsskrb5_release_oid_set(NULL, &handle->mechanisms); + free(handle); + } + if (output_cred_handle) + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + return ret; +} diff --git a/source4/heimdal/lib/gssapi/add_oid_set_member.c b/source4/heimdal/lib/gssapi/krb5/add_oid_set_member.c index ed654fc8c5..b0ec2c60d8 100644 --- a/source4/heimdal/lib/gssapi/add_oid_set_member.c +++ b/source4/heimdal/lib/gssapi/krb5/add_oid_set_member.c @@ -31,11 +31,11 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: add_oid_set_member.c,v 1.8 2003/03/16 17:50:49 lha Exp $"); +RCSID("$Id: add_oid_set_member.c,v 1.10 2006/10/07 22:14:00 lha Exp $"); -OM_uint32 gss_add_oid_set_member ( +OM_uint32 _gsskrb5_add_oid_set_member ( OM_uint32 * minor_status, const gss_OID member_oid, gss_OID_set * oid_set @@ -46,7 +46,8 @@ OM_uint32 gss_add_oid_set_member ( OM_uint32 res; int present; - res = gss_test_oid_set_member(minor_status, member_oid, *oid_set, &present); + res = _gsskrb5_test_oid_set_member(minor_status, member_oid, + *oid_set, &present); if (res != GSS_S_COMPLETE) return res; diff --git a/source4/heimdal/lib/gssapi/address_to_krb5addr.c b/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c index 13a6825f55..9aec53faaa 100644 --- a/source4/heimdal/lib/gssapi/address_to_krb5addr.c +++ b/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c @@ -31,15 +31,15 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" #include <roken.h> krb5_error_code -gss_address_to_krb5addr(OM_uint32 gss_addr_type, - gss_buffer_desc *gss_addr, - int16_t port, - krb5_address *address) +_gsskrb5i_address_to_krb5addr(OM_uint32 gss_addr_type, + gss_buffer_desc *gss_addr, + int16_t port, + krb5_address *address) { int addr_type; struct sockaddr sa; @@ -61,7 +61,7 @@ gss_address_to_krb5addr(OM_uint32 gss_addr_type, return GSS_S_FAILURE; } - problem = krb5_h_addr2sockaddr (gssapi_krb5_context, + problem = krb5_h_addr2sockaddr (_gsskrb5_context, addr_type, gss_addr->value, &sa, @@ -70,7 +70,7 @@ gss_address_to_krb5addr(OM_uint32 gss_addr_type, if (problem) return GSS_S_FAILURE; - problem = krb5_sockaddr2address (gssapi_krb5_context, &sa, address); + problem = krb5_sockaddr2address (_gsskrb5_context, &sa, address); return problem; } diff --git a/source4/heimdal/lib/gssapi/arcfour.c b/source4/heimdal/lib/gssapi/krb5/arcfour.c index 936a20d403..82851f5a78 100644 --- a/source4/heimdal/lib/gssapi/arcfour.c +++ b/source4/heimdal/lib/gssapi/krb5/arcfour.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,9 +31,9 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: arcfour.c,v 1.19 2006/05/04 11:56:50 lha Exp $"); +RCSID("$Id: arcfour.c,v 1.29 2006/10/07 22:14:05 lha Exp $"); /* * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt @@ -57,6 +57,17 @@ RCSID("$Id: arcfour.c,v 1.19 2006/05/04 11:56:50 lha Exp $"); * Confounder[8] */ +/* + * WRAP in DCE-style have a fixed size header, the oid and length over + * the WRAP header is a total of + * GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE + + * GSS_ARCFOUR_WRAP_TOKEN_SIZE byte (ie total of 45 bytes overhead, + * remember the 2 bytes from APPL [0] SEQ). + */ + +#define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32 +#define GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE 13 + static krb5_error_code arcfour_mic_key(krb5_context context, krb5_keyblock *key, @@ -127,13 +138,13 @@ arcfour_mic_cksum(krb5_keyblock *key, unsigned usage, memcpy(ptr + l1, v2, l2); memcpy(ptr + l1 + l2, v3, l3); - ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto); + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); if (ret) { free(ptr); return ret; } - ret = krb5_create_checksum(gssapi_krb5_context, + ret = krb5_create_checksum(_gsskrb5_context, crypto, usage, 0, @@ -144,7 +155,7 @@ arcfour_mic_cksum(krb5_keyblock *key, unsigned usage, memcpy(sgn_cksum, CKSUM.checksum.data, sgn_cksum_sz); free_Checksum(&CKSUM); } - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return ret; } @@ -152,7 +163,7 @@ arcfour_mic_cksum(krb5_keyblock *key, unsigned usage, OM_uint32 _gssapi_get_mic_arcfour(OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, gss_qop_t qop_req, const gss_buffer_t message_buffer, gss_buffer_t message_token, @@ -164,7 +175,7 @@ _gssapi_get_mic_arcfour(OM_uint32 * minor_status, u_char k6_data[16], *p0, *p; RC4_KEY rc4_key; - gssapi_krb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); + _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); message_token->length = total_len; message_token->value = malloc (total_len); @@ -195,28 +206,28 @@ _gssapi_get_mic_arcfour(OM_uint32 * minor_status, message_buffer->value, message_buffer->length, NULL, 0); if (ret) { - gss_release_buffer(minor_status, message_token); + _gsskrb5_release_buffer(minor_status, message_token); *minor_status = ret; return GSS_S_FAILURE; } - ret = arcfour_mic_key(gssapi_krb5_context, key, + ret = arcfour_mic_key(_gsskrb5_context, key, p0 + 16, 8, /* SGN_CKSUM */ k6_data, sizeof(k6_data)); if (ret) { - gss_release_buffer(minor_status, message_token); + _gsskrb5_release_buffer(minor_status, message_token); *minor_status = ret; return GSS_S_FAILURE; } HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - krb5_auth_con_getlocalseqnumber (gssapi_krb5_context, + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, context_handle->auth_context, &seq_number); p = p0 + 8; /* SND_SEQ */ - gssapi_encode_be_om_uint32(seq_number, p); + _gsskrb5_encode_be_om_uint32(seq_number, p); - krb5_auth_con_setlocalseqnumber (gssapi_krb5_context, + krb5_auth_con_setlocalseqnumber (_gsskrb5_context, context_handle->auth_context, ++seq_number); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); @@ -236,7 +247,7 @@ _gssapi_get_mic_arcfour(OM_uint32 * minor_status, OM_uint32 _gssapi_verify_mic_arcfour(OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, const gss_buffer_t message_buffer, const gss_buffer_t token_buffer, gss_qop_t * qop_state, @@ -244,7 +255,7 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status, char *type) { krb5_error_code ret; - int32_t seq_number; + uint32_t seq_number; OM_uint32 omret; u_char SND_SEQ[8], cksum_data[8], *p; char k6_data[16]; @@ -254,7 +265,7 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status, *qop_state = 0; p = token_buffer->value; - omret = gssapi_krb5_verify_header (&p, + omret = _gsskrb5_verify_header (&p, token_buffer->length, (u_char *)type, GSS_KRB5_MECHANISM); @@ -278,7 +289,7 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status, return GSS_S_FAILURE; } - ret = arcfour_mic_key(gssapi_krb5_context, key, + ret = arcfour_mic_key(_gsskrb5_context, key, cksum_data, sizeof(cksum_data), k6_data, sizeof(k6_data)); if (ret) { @@ -302,7 +313,7 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status, memset(k6_data, 0, sizeof(k6_data)); } - gssapi_decode_be_om_uint32(SND_SEQ, &seq_number); + _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); if (context_handle->more_flags & LOCAL) cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); @@ -326,39 +337,8 @@ _gssapi_verify_mic_arcfour(OM_uint32 * minor_status, } OM_uint32 -_gssapi_wrap_size_arcfour(OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, - int conf_req_flag, - gss_qop_t qop_req, - OM_uint32 req_input_size, - OM_uint32 * output_size, - OM_uint32 * padlen, - krb5_keyblock *key) -{ - size_t len, total_len, datalen; - *padlen = 0; - datalen = req_input_size; - len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; - /* if GSS_C_DCE_STYLE is in use: - * - we only need to encapsulate the WRAP token - * - we should not add padding - */ - if (!(context_handle->flags & GSS_C_DCE_STYLE)) { - datalen += 1 /* padding */; - len += datalen; - } - _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); - if (context_handle->flags & GSS_C_DCE_STYLE) { - total_len += datalen; - } - - *output_size = total_len; - return GSS_S_COMPLETE; -} - -OM_uint32 _gssapi_wrap_arcfour(OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, int conf_req_flag, gss_qop_t qop_req, const gss_buffer_t input_message_buffer, @@ -375,19 +355,17 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status, if (conf_state) *conf_state = 0; - datalen = input_message_buffer->length; - len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; - /* if GSS_C_DCE_STYLE is in use: - * - we only need to encapsulate the WRAP token - * - we should not add padding - */ - if (!(context_handle->flags & GSS_C_DCE_STYLE)) { - datalen += 1 /* padding */; - len += datalen; - } - _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); - if (context_handle->flags & GSS_C_DCE_STYLE) { - total_len += datalen; + if ((context_handle->flags & GSS_C_DCE_STYLE) == 0) { + datalen = input_message_buffer->length + 1 /* padding */; + + len = datalen + GSS_ARCFOUR_WRAP_TOKEN_SIZE; + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + } else { + datalen = input_message_buffer->length; + + len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + total_len += datalen; } output_message_buffer->length = total_len; @@ -419,13 +397,13 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status, p = NULL; HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - krb5_auth_con_getlocalseqnumber (gssapi_krb5_context, + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, context_handle->auth_context, &seq_number); - gssapi_encode_be_om_uint32(seq_number, p0 + 8); + _gsskrb5_encode_be_om_uint32(seq_number, p0 + 8); - krb5_auth_con_setlocalseqnumber (gssapi_krb5_context, + krb5_auth_con_setlocalseqnumber (_gsskrb5_context, context_handle->auth_context, ++seq_number); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); @@ -439,9 +417,9 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status, /* p points to data */ p = p0 + GSS_ARCFOUR_WRAP_TOKEN_SIZE; memcpy(p, input_message_buffer->value, input_message_buffer->length); - /* only add padding when GSS_C_DCE_STYLE is not in use */ - if (!(context_handle->flags & GSS_C_DCE_STYLE)) { - p[input_message_buffer->length] = 1; /* PADDING */ + + if ((context_handle->flags & GSS_C_DCE_STYLE) == 0) { + p[input_message_buffer->length] = 1; /* PADDING */ } ret = arcfour_mic_cksum(key, KRB5_KU_USAGE_SEAL, @@ -452,7 +430,7 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status, datalen); if (ret) { *minor_status = ret; - gss_release_buffer(minor_status, output_message_buffer); + _gsskrb5_release_buffer(minor_status, output_message_buffer); return GSS_S_FAILURE; } @@ -466,12 +444,12 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status, for (i = 0; i < 16; i++) Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; } - ret = arcfour_mic_key(gssapi_krb5_context, &Klocal, + ret = arcfour_mic_key(_gsskrb5_context, &Klocal, p0 + 8, 4, /* SND_SEQ */ k6_data, sizeof(k6_data)); memset(Klocaldata, 0, sizeof(Klocaldata)); if (ret) { - gss_release_buffer(minor_status, output_message_buffer); + _gsskrb5_release_buffer(minor_status, output_message_buffer); *minor_status = ret; return GSS_S_FAILURE; } @@ -487,11 +465,11 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status, } memset(k6_data, 0, sizeof(k6_data)); - ret = arcfour_mic_key(gssapi_krb5_context, key, + ret = arcfour_mic_key(_gsskrb5_context, key, p0 + 16, 8, /* SGN_CKSUM */ k6_data, sizeof(k6_data)); if (ret) { - gss_release_buffer(minor_status, output_message_buffer); + _gsskrb5_release_buffer(minor_status, output_message_buffer); *minor_status = ret; return GSS_S_FAILURE; } @@ -513,7 +491,7 @@ _gssapi_wrap_arcfour(OM_uint32 * minor_status, } OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, const gss_buffer_t input_message_buffer, gss_buffer_t output_message_buffer, int *conf_state, @@ -523,15 +501,15 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, u_char Klocaldata[16]; krb5_keyblock Klocal; krb5_error_code ret; - int32_t seq_number; - size_t len, datalen; + uint32_t seq_number; + size_t datalen; OM_uint32 omret; u_char k6_data[16], SND_SEQ[8], Confounder[8]; u_char cksum_data[8]; u_char *p, *p0; int cmp; int conf_flag; - size_t padlen = 0; + size_t padlen = 0, len; if (conf_state) *conf_state = 0; @@ -539,25 +517,34 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, *qop_state = 0; p0 = input_message_buffer->value; - len = input_message_buffer->length; - /* if we have GSS_C_DCE_STYLE in use, we only need to decapsulate the WRAP token */ - if (context_handle->flags & GSS_C_DCE_STYLE) { - if (input_message_buffer->length < (GSS_ARCFOUR_WRAP_TOKEN_OFFSET+GSS_ARCFOUR_WRAP_TOKEN_SIZE)) { - return GSS_S_BAD_MECH; - } - len = GSS_ARCFOUR_WRAP_TOKEN_OFFSET+GSS_ARCFOUR_WRAP_TOKEN_SIZE; + + if ((context_handle->flags & GSS_C_DCE_STYLE) == 0) { + len = input_message_buffer->length; + } else { + len = GSS_ARCFOUR_WRAP_TOKEN_SIZE + + GSS_ARCFOUR_WRAP_TOKEN_DCE_DER_HEADER_SIZE; + if (input_message_buffer->length < len) + return GSS_S_BAD_MECH; } + omret = _gssapi_verify_mech_header(&p0, len, GSS_KRB5_MECHANISM); if (omret) return omret; - p = p0; - datalen = input_message_buffer->length - - (p - ((u_char *)input_message_buffer->value)) - + /* length of mech header */ + len = (p0 - (u_char *)input_message_buffer->value) + GSS_ARCFOUR_WRAP_TOKEN_SIZE; + if (len > input_message_buffer->length) + return GSS_S_BAD_MECH; + + /* length of data */ + datalen = input_message_buffer->length - len; + + p = p0; + if (memcmp(p, "\x02\x01", 2) != 0) return GSS_S_BAD_SIG; p += 2; @@ -577,7 +564,7 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, return GSS_S_BAD_MIC; p = NULL; - ret = arcfour_mic_key(gssapi_krb5_context, key, + ret = arcfour_mic_key(_gsskrb5_context, key, p0 + 16, 8, /* SGN_CKSUM */ k6_data, sizeof(k6_data)); if (ret) { @@ -594,7 +581,7 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, memset(k6_data, 0, sizeof(k6_data)); } - gssapi_decode_be_om_uint32(SND_SEQ, &seq_number); + _gsskrb5_decode_be_om_uint32(SND_SEQ, &seq_number); if (context_handle->more_flags & LOCAL) cmp = memcmp(&SND_SEQ[4], "\xff\xff\xff\xff", 4); @@ -616,7 +603,7 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, for (i = 0; i < 16; i++) Klocaldata[i] = ((u_char *)key->keyvalue.data)[i] ^ 0xF0; } - ret = arcfour_mic_key(gssapi_krb5_context, &Klocal, + ret = arcfour_mic_key(_gsskrb5_context, &Klocal, SND_SEQ, 4, k6_data, sizeof(k6_data)); memset(Klocaldata, 0, sizeof(Klocaldata)); @@ -648,14 +635,14 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, } memset(k6_data, 0, sizeof(k6_data)); - if (!(context_handle->flags & GSS_C_DCE_STYLE)) { - ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen); - if (ret) { - gss_release_buffer(minor_status, output_message_buffer); + if ((context_handle->flags & GSS_C_DCE_STYLE) == 0) { + ret = _gssapi_verify_pad(output_message_buffer, datalen, &padlen); + if (ret) { + _gsskrb5_release_buffer(minor_status, output_message_buffer); *minor_status = 0; return ret; - } - output_message_buffer->length -= padlen; + } + output_message_buffer->length -= padlen; } ret = arcfour_mic_cksum(key, KRB5_KU_USAGE_SEAL, @@ -665,14 +652,14 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, output_message_buffer->value, output_message_buffer->length + padlen); if (ret) { - gss_release_buffer(minor_status, output_message_buffer); + _gsskrb5_release_buffer(minor_status, output_message_buffer); *minor_status = ret; return GSS_S_FAILURE; } cmp = memcmp(cksum_data, p0 + 16, 8); /* SGN_CKSUM */ if (cmp) { - gss_release_buffer(minor_status, output_message_buffer); + _gsskrb5_release_buffer(minor_status, output_message_buffer); *minor_status = 0; return GSS_S_BAD_MIC; } @@ -689,3 +676,79 @@ OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, *minor_status = 0; return GSS_S_COMPLETE; } + +static OM_uint32 +max_wrap_length_arcfour(const gsskrb5_ctx ctx, + krb5_crypto crypto, + size_t input_length, + OM_uint32 *max_input_size) +{ + /* + * if GSS_C_DCE_STYLE is in use: + * - we only need to encapsulate the WRAP token + * However, since this is a fixed since, we just + */ + if (ctx->flags & GSS_C_DCE_STYLE) { + size_t len, total_len; + + len = GSS_ARCFOUR_WRAP_TOKEN_SIZE; + _gssapi_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + + if (input_length < len) + *max_input_size = 0; + else + *max_input_size = input_length - len; + + } else { + size_t extrasize = GSS_ARCFOUR_WRAP_TOKEN_SIZE; + size_t blocksize = 8; + size_t len, total_len; + + len = 8 + input_length + blocksize + extrasize; + + _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + + total_len -= input_length; /* token length */ + if (total_len < input_length) { + *max_input_size = (input_length - total_len); + (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); + } else { + *max_input_size = 0; + } + } + + return GSS_S_COMPLETE; +} + +OM_uint32 +_gssapi_wrap_size_arcfour(OM_uint32 *minor_status, + const gsskrb5_ctx ctx, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ret = max_wrap_length_arcfour(ctx, crypto, + req_output_size, max_input_size); + if (ret != 0) { + _gsskrb5_set_error_string(); + *minor_status = ret; + krb5_crypto_destroy(_gsskrb5_context, crypto); + return GSS_S_FAILURE; + } + + krb5_crypto_destroy(_gsskrb5_context, crypto); + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c new file mode 100644 index 0000000000..f69300b590 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: canonicalize_name.c,v 1.4 2006/10/07 22:14:08 lha Exp $"); + +OM_uint32 _gsskrb5_canonicalize_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + const gss_OID mech_type, + gss_name_t * output_name + ) +{ + return _gsskrb5_duplicate_name (minor_status, input_name, output_name); +} diff --git a/source4/heimdal/lib/gssapi/cfx.c b/source4/heimdal/lib/gssapi/krb5/cfx.c index ef7907c0de..cb3f9ee5d3 100755 --- a/source4/heimdal/lib/gssapi/cfx.c +++ b/source4/heimdal/lib/gssapi/krb5/cfx.c @@ -30,9 +30,9 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: cfx.c,v 1.19 2006/05/05 10:26:43 lha Exp $"); +RCSID("$Id: cfx.c,v 1.24 2006/10/24 21:13:22 lha Exp $"); /* * Implementation of draft-ietf-krb-wg-gssapi-cfx-06.txt @@ -42,14 +42,13 @@ RCSID("$Id: cfx.c,v 1.19 2006/05/05 10:26:43 lha Exp $"); #define CFXSealed (1 << 1) #define CFXAcceptorSubkey (1 << 2) -static krb5_error_code -wrap_length_cfx(krb5_crypto crypto, - int conf_req_flag, - size_t input_length, - size_t *output_length, - size_t *cksumsize, - uint16_t *padlength, - size_t *padsize) +krb5_error_code +_gsskrb5cfx_wrap_length_cfx(krb5_crypto crypto, + int conf_req_flag, + size_t input_length, + size_t *output_length, + size_t *cksumsize, + uint16_t *padlength) { krb5_error_code ret; krb5_cksumtype type; @@ -58,39 +57,37 @@ wrap_length_cfx(krb5_crypto crypto, *output_length = sizeof(gss_cfx_wrap_token_desc); *padlength = 0; - ret = krb5_crypto_get_checksum_type(gssapi_krb5_context, crypto, &type); - if (ret) { + ret = krb5_crypto_get_checksum_type(_gsskrb5_context, crypto, &type); + if (ret) return ret; - } - ret = krb5_checksumsize(gssapi_krb5_context, type, cksumsize); - if (ret) { + ret = krb5_checksumsize(_gsskrb5_context, type, cksumsize); + if (ret) return ret; - } if (conf_req_flag) { + size_t padsize; /* Header is concatenated with data before encryption */ input_length += sizeof(gss_cfx_wrap_token_desc); - ret = krb5_crypto_getpadsize(gssapi_krb5_context, crypto, padsize); + ret = krb5_crypto_getpadsize(_gsskrb5_context, crypto, &padsize); if (ret) { return ret; } - if (*padsize > 1) { + if (padsize > 1) { /* XXX check this */ - *padlength = *padsize - (input_length % *padsize); - } + *padlength = padsize - (input_length % padsize); - /* We add the pad ourselves (noted here for completeness only) */ - input_length += *padlength; + /* We add the pad ourselves (noted here for completeness only) */ + input_length += *padlength; + } - *output_length += krb5_get_wrapped_length(gssapi_krb5_context, + *output_length += krb5_get_wrapped_length(_gsskrb5_context, crypto, input_length); } else { /* Checksum is concatenated with data */ *output_length += input_length + *cksumsize; - *padsize = 0; } assert(*output_length > input_length); @@ -98,42 +95,94 @@ wrap_length_cfx(krb5_crypto crypto, return 0; } +krb5_error_code +_gsskrb5cfx_max_wrap_length_cfx(krb5_crypto crypto, + int conf_req_flag, + size_t input_length, + OM_uint32 *output_length) +{ + krb5_error_code ret; + + *output_length = 0; + + /* 16-byte header is always first */ + if (input_length < 16) + return 0; + input_length -= 16; + + if (conf_req_flag) { + size_t wrapped_size, sz; + + wrapped_size = input_length + 1; + do { + wrapped_size--; + sz = krb5_get_wrapped_length(_gsskrb5_context, + crypto, wrapped_size); + } while (wrapped_size && sz > input_length); + if (wrapped_size == 0) { + *output_length = 0; + return 0; + } + + /* inner header */ + if (wrapped_size < 16) { + *output_length = 0; + return 0; + } + wrapped_size -= 16; + + *output_length = wrapped_size; + } else { + krb5_cksumtype type; + size_t cksumsize; + + ret = krb5_crypto_get_checksum_type(_gsskrb5_context, crypto, &type); + if (ret) + return ret; + + ret = krb5_checksumsize(_gsskrb5_context, type, &cksumsize); + if (ret) + return ret; + + if (input_length < cksumsize) + return 0; + + /* Checksum is concatenated with data */ + *output_length = input_length - cksumsize; + } + + return 0; +} + + OM_uint32 _gssapi_wrap_size_cfx(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, int conf_req_flag, gss_qop_t qop_req, - OM_uint32 req_input_size, - OM_uint32 *output_len, - OM_uint32 *padsize, + OM_uint32 req_output_size, + OM_uint32 *max_input_size, krb5_keyblock *key) { krb5_error_code ret; krb5_crypto crypto; - uint16_t pad_length; - size_t pad_size; - size_t output_length, cksumsize; - ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto); + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; return GSS_S_FAILURE; } - ret = wrap_length_cfx(crypto, conf_req_flag, - req_input_size, - &output_length, &cksumsize, &pad_length, &pad_size); + ret = _gsskrb5cfx_max_wrap_length_cfx(crypto, conf_req_flag, + req_output_size, max_input_size); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_FAILURE; } - *output_len = output_length; - *padsize = pad_size; - - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_COMPLETE; } @@ -183,7 +232,7 @@ rrc_rotate(void *data, size_t len, uint16_t rrc, krb5_boolean unrotate) } OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, int conf_req_flag, gss_qop_t qop_req, const gss_buffer_t input_message_buffer, @@ -199,23 +248,22 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, size_t wrapped_len, cksumsize; uint16_t padlength, rrc = 0; int32_t seq_number; - size_t padsize; u_char *p; - ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto); + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; return GSS_S_FAILURE; } - ret = wrap_length_cfx(crypto, conf_req_flag, - input_message_buffer->length, - &wrapped_len, &cksumsize, &padlength, &padsize); + ret = _gsskrb5cfx_wrap_length_cfx(crypto, conf_req_flag, + input_message_buffer->length, + &wrapped_len, &cksumsize, &padlength); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_FAILURE; } @@ -226,7 +274,7 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, output_message_buffer->value = malloc(output_message_buffer->length); if (output_message_buffer->value == NULL) { *minor_status = ENOMEM; - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_FAILURE; } @@ -276,12 +324,12 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, token->RRC[1] = 0; HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - krb5_auth_con_getlocalseqnumber(gssapi_krb5_context, + krb5_auth_con_getlocalseqnumber(_gsskrb5_context, context_handle->auth_context, &seq_number); - gssapi_encode_be_om_uint32(0, &token->SND_SEQ[0]); - gssapi_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); - krb5_auth_con_setlocalseqnumber(gssapi_krb5_context, + _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]); + _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); + krb5_auth_con_setlocalseqnumber(_gsskrb5_context, context_handle->auth_context, ++seq_number); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); @@ -316,16 +364,16 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, memcpy(p + input_message_buffer->length + padlength, token, sizeof(*token)); - ret = krb5_encrypt(gssapi_krb5_context, crypto, + ret = krb5_encrypt(_gsskrb5_context, crypto, usage, p, input_message_buffer->length + padlength + sizeof(*token), &cipher); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); - gss_release_buffer(minor_status, output_message_buffer); + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); return GSS_S_FAILURE; } assert(sizeof(*token) + cipher.length == wrapped_len); @@ -334,10 +382,10 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, ret = rrc_rotate(cipher.data, cipher.length, rrc, FALSE); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); - gss_release_buffer(minor_status, output_message_buffer); + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); return GSS_S_FAILURE; } memcpy(p, cipher.data, cipher.length); @@ -349,23 +397,23 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, buf = malloc(input_message_buffer->length + sizeof(*token)); if (buf == NULL) { *minor_status = ENOMEM; - krb5_crypto_destroy(gssapi_krb5_context, crypto); - gss_release_buffer(minor_status, output_message_buffer); + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); return GSS_S_FAILURE; } memcpy(buf, input_message_buffer->value, input_message_buffer->length); memcpy(buf + input_message_buffer->length, token, sizeof(*token)); - ret = krb5_create_checksum(gssapi_krb5_context, crypto, + ret = krb5_create_checksum(_gsskrb5_context, crypto, usage, 0, buf, input_message_buffer->length + sizeof(*token), &cksum); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); - gss_release_buffer(minor_status, output_message_buffer); + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); free(buf); return GSS_S_FAILURE; } @@ -386,17 +434,17 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, ret = rrc_rotate(p, input_message_buffer->length + cksum.checksum.length, rrc, FALSE); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); - gss_release_buffer(minor_status, output_message_buffer); + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); free_Checksum(&cksum); return GSS_S_FAILURE; } free_Checksum(&cksum); } - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); if (conf_state != NULL) { *conf_state = conf_req_flag; @@ -407,7 +455,7 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, } OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, const gss_buffer_t input_message_buffer, gss_buffer_t output_message_buffer, int *conf_state, @@ -470,8 +518,8 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, /* * Check sequence number */ - gssapi_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); - gssapi_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); if (seq_number_hi) { /* no support for 64-bit sequence numbers */ *minor_status = ERANGE; @@ -483,7 +531,7 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, if (ret != 0) { *minor_status = 0; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - gss_release_buffer(minor_status, output_message_buffer); + _gsskrb5_release_buffer(minor_status, output_message_buffer); return ret; } HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); @@ -491,9 +539,9 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, /* * Decrypt and/or verify checksum */ - ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto); + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; return GSS_S_FAILURE; } @@ -511,23 +559,23 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, /* Rotate by RRC; bogus to do this in-place XXX */ *minor_status = rrc_rotate(p, len, rrc, TRUE); if (*minor_status != 0) { - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_FAILURE; } if (token_flags & CFXSealed) { - ret = krb5_decrypt(gssapi_krb5_context, crypto, usage, + ret = krb5_decrypt(_gsskrb5_context, crypto, usage, p, len, &data); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_BAD_MIC; } /* Check that there is room for the pad and token header */ if (data.length < ec + sizeof(*token)) { - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); krb5_data_free(&data); return GSS_S_DEFECTIVE_TOKEN; } @@ -540,7 +588,7 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, /* Check the integrity of the header */ if (memcmp(p, token, sizeof(*token)) != 0) { - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); krb5_data_free(&data); return GSS_S_BAD_MIC; } @@ -551,12 +599,12 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, Checksum cksum; /* Determine checksum type */ - ret = krb5_crypto_get_checksum_type(gssapi_krb5_context, + ret = krb5_crypto_get_checksum_type(_gsskrb5_context, crypto, &cksum.cksumtype); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_FAILURE; } @@ -565,7 +613,7 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, /* Check we have at least as much data as the checksum */ if (len < cksum.checksum.length) { *minor_status = ERANGE; - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_BAD_MIC; } @@ -577,7 +625,7 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, output_message_buffer->value = malloc(len + sizeof(*token)); if (output_message_buffer->value == NULL) { *minor_status = ENOMEM; - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_FAILURE; } @@ -594,21 +642,21 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, token->RRC[0] = 0; token->RRC[1] = 0; - ret = krb5_verify_checksum(gssapi_krb5_context, crypto, + ret = krb5_verify_checksum(_gsskrb5_context, crypto, usage, output_message_buffer->value, len + sizeof(*token), &cksum); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); - gss_release_buffer(minor_status, output_message_buffer); + krb5_crypto_destroy(_gsskrb5_context, crypto); + _gsskrb5_release_buffer(minor_status, output_message_buffer); return GSS_S_BAD_MIC; } } - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); if (qop_state != NULL) { *qop_state = GSS_C_QOP_DEFAULT; @@ -619,7 +667,7 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, } OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, gss_qop_t qop_req, const gss_buffer_t message_buffer, gss_buffer_t message_token, @@ -634,9 +682,9 @@ OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, size_t len; int32_t seq_number; - ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto); + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; return GSS_S_FAILURE; } @@ -645,7 +693,7 @@ OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, buf = malloc(len); if (buf == NULL) { *minor_status = ENOMEM; - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_FAILURE; } @@ -662,12 +710,12 @@ OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, memset(token->Filler, 0xFF, 5); HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - krb5_auth_con_getlocalseqnumber(gssapi_krb5_context, + krb5_auth_con_getlocalseqnumber(_gsskrb5_context, context_handle->auth_context, &seq_number); - gssapi_encode_be_om_uint32(0, &token->SND_SEQ[0]); - gssapi_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); - krb5_auth_con_setlocalseqnumber(gssapi_krb5_context, + _gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]); + _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]); + krb5_auth_con_setlocalseqnumber(_gsskrb5_context, context_handle->auth_context, ++seq_number); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); @@ -678,16 +726,16 @@ OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, usage = KRB5_KU_USAGE_ACCEPTOR_SIGN; } - ret = krb5_create_checksum(gssapi_krb5_context, crypto, + ret = krb5_create_checksum(_gsskrb5_context, crypto, usage, 0, buf, len, &cksum); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); free(buf); return GSS_S_FAILURE; } - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); /* Determine MIC length */ message_token->length = sizeof(*token) + cksum.checksum.length; @@ -712,7 +760,7 @@ OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, } OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, const gss_buffer_t message_buffer, const gss_buffer_t token_buffer, gss_qop_t *qop_state, @@ -763,8 +811,8 @@ OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, /* * Check sequence number */ - gssapi_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); - gssapi_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi); + _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo); if (seq_number_hi) { *minor_status = ERANGE; return GSS_S_UNSEQ_TOKEN; @@ -782,19 +830,19 @@ OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, /* * Verify checksum */ - ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto); + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; return GSS_S_FAILURE; } - ret = krb5_crypto_get_checksum_type(gssapi_krb5_context, crypto, + ret = krb5_crypto_get_checksum_type(_gsskrb5_context, crypto, &cksum.cksumtype); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_FAILURE; } @@ -810,21 +858,21 @@ OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, buf = malloc(message_buffer->length + sizeof(*token)); if (buf == NULL) { *minor_status = ENOMEM; - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); return GSS_S_FAILURE; } memcpy(buf, message_buffer->value, message_buffer->length); memcpy(buf + message_buffer->length, token, sizeof(*token)); - ret = krb5_verify_checksum(gssapi_krb5_context, crypto, + ret = krb5_verify_checksum(_gsskrb5_context, crypto, usage, buf, sizeof(*token) + message_buffer->length, &cksum); + krb5_crypto_destroy(_gsskrb5_context, crypto); if (ret != 0) { - gssapi_krb5_set_error_string(); + _gsskrb5_set_error_string(); *minor_status = ret; - krb5_crypto_destroy(gssapi_krb5_context, crypto); free(buf); return GSS_S_BAD_MIC; } diff --git a/source4/heimdal/lib/gssapi/cfx.h b/source4/heimdal/lib/gssapi/krb5/cfx.h index d9bdd9da19..1120544fbe 100755 --- a/source4/heimdal/lib/gssapi/cfx.h +++ b/source4/heimdal/lib/gssapi/krb5/cfx.h @@ -30,7 +30,7 @@ * SUCH DAMAGE. */ -/* $Id: cfx.h,v 1.5 2003/09/22 21:48:35 lha Exp $ */ +/* $Id: cfx.h,v 1.7 2006/07/19 14:16:33 lha Exp $ */ #ifndef GSSAPI_CFX_H_ #define GSSAPI_CFX_H_ 1 @@ -62,44 +62,19 @@ typedef struct gss_cfx_delete_token_desc_struct { u_char SND_SEQ[8]; } gss_cfx_delete_token_desc, *gss_cfx_delete_token; -OM_uint32 _gssapi_wrap_size_cfx(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, - int conf_req_flag, - gss_qop_t qop_req, - OM_uint32 req_input_size, - OM_uint32 *output_len, - OM_uint32 *padlen, - krb5_keyblock *key); - -OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, - int conf_req_flag, - gss_qop_t qop_req, - const gss_buffer_t input_message_buffer, - int *conf_state, - gss_buffer_t output_message_buffer, - krb5_keyblock *key); +krb5_error_code +_gsskrb5cfx_wrap_length_cfx(krb5_crypto crypto, + int conf_req_flag, + size_t input_length, + size_t *output_length, + size_t *cksumsize, + uint16_t *padlength); -OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, - const gss_buffer_t input_message_buffer, - gss_buffer_t output_message_buffer, - int *conf_state, - gss_qop_t *qop_state, - krb5_keyblock *key); - -OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, - gss_qop_t qop_req, - const gss_buffer_t message_buffer, - gss_buffer_t message_token, - krb5_keyblock *key); +krb5_error_code +_gsskrb5cfx_max_wrap_length_cfx(krb5_crypto crypto, + int conf_req_flag, + size_t input_length, + OM_uint32 *output_length); -OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, - const gss_buffer_t message_buffer, - const gss_buffer_t token_buffer, - gss_qop_t *qop_state, - krb5_keyblock *key); #endif /* GSSAPI_CFX_H_ */ diff --git a/source4/heimdal/lib/gssapi/krb5/compare_name.c b/source4/heimdal/lib/gssapi/krb5/compare_name.c new file mode 100644 index 0000000000..3e0f7edfee --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/compare_name.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: compare_name.c,v 1.7 2006/10/07 22:14:15 lha Exp $"); + +OM_uint32 _gsskrb5_compare_name + (OM_uint32 * minor_status, + const gss_name_t name1, + const gss_name_t name2, + int * name_equal + ) +{ + krb5_const_principal princ1 = (krb5_const_principal)name1; + krb5_const_principal princ2 = (krb5_const_principal)name2; + + GSSAPI_KRB5_INIT(); + + *name_equal = krb5_principal_compare (_gsskrb5_context, + princ1, princ2); + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/compat.c b/source4/heimdal/lib/gssapi/krb5/compat.c index 5605c48023..0ea2fce0e8 100644 --- a/source4/heimdal/lib/gssapi/compat.c +++ b/source4/heimdal/lib/gssapi/krb5/compat.c @@ -31,42 +31,42 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: compat.c,v 1.10 2005/05/30 20:51:51 lha Exp $"); +RCSID("$Id: compat.c,v 1.13 2006/10/07 22:14:17 lha Exp $"); -krb5_error_code -_gss_check_compat(OM_uint32 *minor_status, gss_name_t name, - const char *option, krb5_boolean *compat, - krb5_boolean match_val) +static krb5_error_code +check_compat(OM_uint32 *minor_status, krb5_const_principal name, + const char *option, krb5_boolean *compat, + krb5_boolean match_val) { krb5_error_code ret = 0; char **p, **q; krb5_principal match; - p = krb5_config_get_strings(gssapi_krb5_context, NULL, "gssapi", + p = krb5_config_get_strings(_gsskrb5_context, NULL, "gssapi", option, NULL); if(p == NULL) return 0; match = NULL; for(q = p; *q; q++) { - ret = krb5_parse_name(gssapi_krb5_context, *q, &match); + ret = krb5_parse_name(_gsskrb5_context, *q, &match); if (ret) break; - if (krb5_principal_match(gssapi_krb5_context, name, match)) { + if (krb5_principal_match(_gsskrb5_context, name, match)) { *compat = match_val; break; } - krb5_free_principal(gssapi_krb5_context, match); + krb5_free_principal(_gsskrb5_context, match); match = NULL; } if (match) - krb5_free_principal(gssapi_krb5_context, match); + krb5_free_principal(_gsskrb5_context, match); krb5_config_free_strings(p); if (ret) { @@ -83,18 +83,18 @@ _gss_check_compat(OM_uint32 *minor_status, gss_name_t name, */ OM_uint32 -_gss_DES3_get_mic_compat(OM_uint32 *minor_status, gss_ctx_id_t ctx) +_gss_DES3_get_mic_compat(OM_uint32 *minor_status, gsskrb5_ctx ctx) { krb5_boolean use_compat = FALSE; OM_uint32 ret; if ((ctx->more_flags & COMPAT_OLD_DES3_SELECTED) == 0) { - ret = _gss_check_compat(minor_status, ctx->target, - "broken_des3_mic", &use_compat, TRUE); + ret = check_compat(minor_status, ctx->target, + "broken_des3_mic", &use_compat, TRUE); if (ret) return ret; - ret = _gss_check_compat(minor_status, ctx->target, - "correct_des3_mic", &use_compat, FALSE); + ret = check_compat(minor_status, ctx->target, + "correct_des3_mic", &use_compat, FALSE); if (ret) return ret; @@ -105,6 +105,7 @@ _gss_DES3_get_mic_compat(OM_uint32 *minor_status, gss_ctx_id_t ctx) return 0; } +#if 0 OM_uint32 gss_krb5_compat_des3_mic(OM_uint32 *minor_status, gss_ctx_id_t ctx, int on) { @@ -121,34 +122,4 @@ gss_krb5_compat_des3_mic(OM_uint32 *minor_status, gss_ctx_id_t ctx, int on) return 0; } - -/* - * For compatability with the Windows SPNEGO implementation, the - * default is to ignore the mechListMIC unless the initiator specified - * CFX or configured in krb5.conf with the option - * [gssapi]require_mechlist_mic=target-principal-pattern. - * The option is valid for both initiator and acceptor. - */ -OM_uint32 -_gss_spnego_require_mechlist_mic(OM_uint32 *minor_status, - gss_ctx_id_t ctx, - krb5_boolean *require_mic) -{ - OM_uint32 ret; - int is_cfx = 0; - - gsskrb5_is_cfx(ctx, &is_cfx); - if (is_cfx) { - /* CFX session key was used */ - *require_mic = TRUE; - } else { - *require_mic = FALSE; - ret = _gss_check_compat(minor_status, ctx->target, - "require_mechlist_mic", - require_mic, TRUE); - if (ret) - return ret; - } - *minor_status = 0; - return GSS_S_COMPLETE; -} +#endif diff --git a/source4/heimdal/lib/gssapi/context_time.c b/source4/heimdal/lib/gssapi/krb5/context_time.c index ee1dc6fe93..4e9d9f5d1d 100644 --- a/source4/heimdal/lib/gssapi/context_time.c +++ b/source4/heimdal/lib/gssapi/krb5/context_time.c @@ -31,12 +31,12 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: context_time.c,v 1.11 2005/12/05 09:19:52 lha Exp $"); +RCSID("$Id: context_time.c,v 1.13 2006/10/07 22:14:19 lha Exp $"); OM_uint32 -gssapi_lifetime_left(OM_uint32 *minor_status, +_gsskrb5_lifetime_left(OM_uint32 *minor_status, OM_uint32 lifetime, OM_uint32 *lifetime_rec) { @@ -48,10 +48,10 @@ gssapi_lifetime_left(OM_uint32 *minor_status, return GSS_S_COMPLETE; } - kret = krb5_timeofday(gssapi_krb5_context, &timeret); + kret = krb5_timeofday(_gsskrb5_context, &timeret); if (kret) { *minor_status = kret; - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); return GSS_S_FAILURE; } @@ -64,7 +64,7 @@ gssapi_lifetime_left(OM_uint32 *minor_status, } -OM_uint32 gss_context_time +OM_uint32 _gsskrb5_context_time (OM_uint32 * minor_status, const gss_ctx_id_t context_handle, OM_uint32 * time_rec @@ -72,14 +72,15 @@ OM_uint32 gss_context_time { OM_uint32 lifetime; OM_uint32 major_status; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; GSSAPI_KRB5_INIT (); - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - lifetime = context_handle->lifetime; - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + lifetime = ctx->lifetime; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); - major_status = gssapi_lifetime_left(minor_status, lifetime, time_rec); + major_status = _gsskrb5_lifetime_left(minor_status, lifetime, time_rec); if (major_status != GSS_S_COMPLETE) return major_status; diff --git a/source4/heimdal/lib/gssapi/copy_ccache.c b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c index 782b701e44..99aa2ccb43 100644 --- a/source4/heimdal/lib/gssapi/copy_ccache.c +++ b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c @@ -31,10 +31,11 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: copy_ccache.c,v 1.13 2005/11/28 23:05:44 lha Exp $"); +RCSID("$Id: copy_ccache.c,v 1.15 2006/10/07 22:14:22 lha Exp $"); +#if 0 OM_uint32 gss_krb5_copy_ccache(OM_uint32 *minor_status, gss_cred_id_t cred, @@ -50,36 +51,37 @@ gss_krb5_copy_ccache(OM_uint32 *minor_status, return GSS_S_FAILURE; } - kret = krb5_cc_copy_cache(gssapi_krb5_context, cred->ccache, out); + kret = krb5_cc_copy_cache(_gsskrb5_context, cred->ccache, out); HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); if (kret) { *minor_status = kret; - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); return GSS_S_FAILURE; } *minor_status = 0; return GSS_S_COMPLETE; } +#endif OM_uint32 -gss_krb5_import_cred(OM_uint32 *minor_status, +_gsskrb5_import_cred(OM_uint32 *minor_status, krb5_ccache id, krb5_principal keytab_principal, krb5_keytab keytab, gss_cred_id_t *cred) { krb5_error_code kret; - gss_cred_id_t handle; + gsskrb5_cred handle; OM_uint32 ret; *cred = NULL; GSSAPI_KRB5_INIT (); - handle = (gss_cred_id_t)calloc(1, sizeof(*handle)); - if (handle == GSS_C_NO_CREDENTIAL) { - gssapi_krb5_clear_status (); + handle = calloc(1, sizeof(*handle)); + if (handle == NULL) { + _gsskrb5_clear_status (); *minor_status = ENOMEM; return (GSS_S_FAILURE); } @@ -92,11 +94,11 @@ gss_krb5_import_cred(OM_uint32 *minor_status, handle->usage |= GSS_C_INITIATE; - kret = krb5_cc_get_principal(gssapi_krb5_context, id, + kret = krb5_cc_get_principal(_gsskrb5_context, id, &handle->principal); if (kret) { free(handle); - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = kret; return GSS_S_FAILURE; } @@ -104,34 +106,34 @@ gss_krb5_import_cred(OM_uint32 *minor_status, if (keytab_principal) { krb5_boolean match; - match = krb5_principal_compare(gssapi_krb5_context, + match = krb5_principal_compare(_gsskrb5_context, handle->principal, keytab_principal); if (match == FALSE) { - krb5_free_principal(gssapi_krb5_context, handle->principal); + krb5_free_principal(_gsskrb5_context, handle->principal); free(handle); - gssapi_krb5_clear_status (); + _gsskrb5_clear_status (); *minor_status = EINVAL; return GSS_S_FAILURE; } } - ret = _gssapi_krb5_ccache_lifetime(minor_status, + ret = __gsskrb5_ccache_lifetime(minor_status, id, handle->principal, &handle->lifetime); if (ret != GSS_S_COMPLETE) { - krb5_free_principal(gssapi_krb5_context, handle->principal); + krb5_free_principal(_gsskrb5_context, handle->principal); free(handle); return ret; } - kret = krb5_cc_get_full_name(gssapi_krb5_context, id, &str); + kret = krb5_cc_get_full_name(_gsskrb5_context, id, &str); if (kret) goto out; - kret = krb5_cc_resolve(gssapi_krb5_context, str, &handle->ccache); + kret = krb5_cc_resolve(_gsskrb5_context, str, &handle->ccache); free(str); if (kret) goto out; @@ -144,18 +146,18 @@ gss_krb5_import_cred(OM_uint32 *minor_status, handle->usage |= GSS_C_ACCEPT; if (keytab_principal && handle->principal == NULL) { - kret = krb5_copy_principal(gssapi_krb5_context, + kret = krb5_copy_principal(_gsskrb5_context, keytab_principal, &handle->principal); if (kret) goto out; } - kret = krb5_kt_get_full_name(gssapi_krb5_context, keytab, &str); + kret = krb5_kt_get_full_name(_gsskrb5_context, keytab, &str); if (kret) goto out; - kret = krb5_kt_resolve(gssapi_krb5_context, str, &handle->keytab); + kret = krb5_kt_resolve(_gsskrb5_context, str, &handle->keytab); free(str); if (kret) goto out; @@ -163,10 +165,10 @@ gss_krb5_import_cred(OM_uint32 *minor_status, if (id || keytab) { - ret = gss_create_empty_oid_set(minor_status, &handle->mechanisms); + ret = _gsskrb5_create_empty_oid_set(minor_status, &handle->mechanisms); if (ret == GSS_S_COMPLETE) - ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, - &handle->mechanisms); + ret = _gsskrb5_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, + &handle->mechanisms); if (ret != GSS_S_COMPLETE) { kret = *minor_status; goto out; @@ -174,107 +176,16 @@ gss_krb5_import_cred(OM_uint32 *minor_status, } *minor_status = 0; - *cred = handle; + *cred = (gss_cred_id_t)handle; return GSS_S_COMPLETE; out: - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); if (handle->principal) - krb5_free_principal(gssapi_krb5_context, handle->principal); + krb5_free_principal(_gsskrb5_context, handle->principal); HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); free(handle); *minor_status = kret; return GSS_S_FAILURE; } - -OM_uint32 -gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, - gss_ctx_id_t context_handle, - int ad_type, - gss_buffer_t ad_data) -{ - krb5_error_code ret; - krb5_data data; - - ad_data->value = NULL; - ad_data->length = 0; - - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - if (context_handle->ticket == NULL) { - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - ret = krb5_ticket_get_authorization_data_type(gssapi_krb5_context, - context_handle->ticket, - ad_type, - &data); - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - ad_data->value = malloc(data.length); - if (ad_data->value == NULL) { - krb5_data_free(&data); - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - - ad_data->length = data.length; - memcpy(ad_data->value, data.data, ad_data->length); - krb5_data_free(&data); - - *minor_status = 0; - return GSS_S_COMPLETE; -} - -OM_uint32 -gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status, - gss_ctx_id_t context_handle, - time_t *authtime) -{ - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - if (context_handle->ticket == NULL) { - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - *authtime = context_handle->ticket->ticket.authtime; - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - - *minor_status = 0; - return GSS_S_COMPLETE; -} - -OM_uint32 gss_krb5_copy_service_keyblock - (OM_uint32 *minor_status, - gss_ctx_id_t context_handle, - struct EncryptionKey **out) -{ - krb5_error_code ret; - - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - if (context_handle->service_keyblock == NULL) { - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - *minor_status = EINVAL; - return GSS_S_FAILURE; - } - - ret = krb5_copy_keyblock(gssapi_krb5_context, - context_handle->service_keyblock, - out); - - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - if (ret) { - *minor_status = ret; - return GSS_S_FAILURE; - } - - *minor_status = 0; - return GSS_S_COMPLETE; -} diff --git a/source4/heimdal/lib/gssapi/create_emtpy_oid_set.c b/source4/heimdal/lib/gssapi/krb5/create_emtpy_oid_set.c index 1a25e0d781..550995125a 100644 --- a/source4/heimdal/lib/gssapi/create_emtpy_oid_set.c +++ b/source4/heimdal/lib/gssapi/krb5/create_emtpy_oid_set.c @@ -31,11 +31,11 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: create_emtpy_oid_set.c,v 1.5 2003/03/16 17:47:07 lha Exp $"); +RCSID("$Id: create_emtpy_oid_set.c,v 1.7 2006/10/07 22:14:24 lha Exp $"); -OM_uint32 gss_create_empty_oid_set ( +OM_uint32 _gsskrb5_create_empty_oid_set ( OM_uint32 * minor_status, gss_OID_set * oid_set ) diff --git a/source4/heimdal/lib/gssapi/decapsulate.c b/source4/heimdal/lib/gssapi/krb5/decapsulate.c index 08df361776..eadec1ef03 100644 --- a/source4/heimdal/lib/gssapi/decapsulate.c +++ b/source4/heimdal/lib/gssapi/krb5/decapsulate.c @@ -31,9 +31,9 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: decapsulate.c,v 1.12 2005/06/16 20:40:49 lha Exp $"); +RCSID("$Id: decapsulate.c,v 1.16 2006/10/07 22:14:26 lha Exp $"); /* * return the length of the mechanism in token or -1 @@ -41,7 +41,7 @@ RCSID("$Id: decapsulate.c,v 1.12 2005/06/16 20:40:49 lha Exp $"); */ ssize_t -gssapi_krb5_get_mech (const u_char *ptr, +_gsskrb5_get_mech (const u_char *ptr, size_t total_len, const u_char **mech_ret) { @@ -76,7 +76,7 @@ _gssapi_verify_mech_header(u_char **str, const u_char *p; ssize_t mech_len; - mech_len = gssapi_krb5_get_mech (*str, total_len, &p); + mech_len = _gsskrb5_get_mech (*str, total_len, &p); if (mech_len < 0) return GSS_S_DEFECTIVE_TOKEN; @@ -92,9 +92,9 @@ _gssapi_verify_mech_header(u_char **str, } OM_uint32 -gssapi_krb5_verify_header(u_char **str, +_gsskrb5_verify_header(u_char **str, size_t total_len, - const u_char *type, + const void *type, gss_OID oid) { OM_uint32 ret; @@ -110,7 +110,7 @@ gssapi_krb5_verify_header(u_char **str, if (len < 2) return GSS_S_DEFECTIVE_TOKEN; - if ((*str)[0] != type[0] || (*str)[1] != type[1]) + if (memcmp (*str, type, 2) != 0) return GSS_S_DEFECTIVE_TOKEN; *str += 2; @@ -154,17 +154,17 @@ _gssapi_decapsulate( */ OM_uint32 -gssapi_krb5_decapsulate(OM_uint32 *minor_status, +_gsskrb5_decapsulate(OM_uint32 *minor_status, gss_buffer_t input_token_buffer, krb5_data *out_data, - const char *type, + const void *type, gss_OID oid) { u_char *p; OM_uint32 ret; p = input_token_buffer->value; - ret = gssapi_krb5_verify_header(&p, + ret = _gsskrb5_verify_header(&p, input_token_buffer->length, type, oid); diff --git a/source4/heimdal/lib/gssapi/delete_sec_context.c b/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c index f1842def7c..e890d7d2c2 100644 --- a/source4/heimdal/lib/gssapi/delete_sec_context.c +++ b/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c @@ -31,16 +31,17 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: delete_sec_context.c,v 1.16 2006/01/16 13:12:29 lha Exp $"); +RCSID("$Id: delete_sec_context.c,v 1.19 2006/10/07 22:14:28 lha Exp $"); -OM_uint32 gss_delete_sec_context - (OM_uint32 * minor_status, - gss_ctx_id_t * context_handle, - gss_buffer_t output_token - ) +OM_uint32 +_gsskrb5_delete_sec_context(OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token) { + gsskrb5_ctx ctx; + GSSAPI_KRB5_INIT (); *minor_status = 0; @@ -53,31 +54,27 @@ OM_uint32 gss_delete_sec_context if (*context_handle == GSS_C_NO_CONTEXT) return GSS_S_COMPLETE; - HEIMDAL_MUTEX_lock(&(*context_handle)->ctx_id_mutex); + ctx = (gsskrb5_ctx) *context_handle; + *context_handle = GSS_C_NO_CONTEXT; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); - krb5_auth_con_free (gssapi_krb5_context, - (*context_handle)->auth_context); - if((*context_handle)->source) - krb5_free_principal (gssapi_krb5_context, - (*context_handle)->source); - if((*context_handle)->target) - krb5_free_principal (gssapi_krb5_context, - (*context_handle)->target); - if ((*context_handle)->ticket) - krb5_free_ticket (gssapi_krb5_context, - (*context_handle)->ticket); - if ((*context_handle)->service_keyblock) - krb5_free_keyblock (gssapi_krb5_context, - (*context_handle)->service_keyblock); - if((*context_handle)->order) - _gssapi_msg_order_destroy(&(*context_handle)->order); - if ((*context_handle)->fwd_data.length > 0) - free((*context_handle)->fwd_data.data); + krb5_auth_con_free (_gsskrb5_context, ctx->auth_context); + if(ctx->source) + krb5_free_principal (_gsskrb5_context, ctx->source); + if(ctx->target) + krb5_free_principal (_gsskrb5_context, ctx->target); + if (ctx->ticket) + krb5_free_ticket (_gsskrb5_context, ctx->ticket); + if(ctx->order) + _gssapi_msg_order_destroy(&ctx->order); + if (ctx->service_keyblock) + krb5_free_keyblock (_gsskrb5_context, ctx->service_keyblock); + krb5_data_free(&ctx->fwd_data); - HEIMDAL_MUTEX_unlock(&(*context_handle)->ctx_id_mutex); - HEIMDAL_MUTEX_destroy(&(*context_handle)->ctx_id_mutex); - memset(*context_handle, 0, sizeof(**context_handle)); - free (*context_handle); - *context_handle = GSS_C_NO_CONTEXT; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + memset(ctx, 0, sizeof(*ctx)); + free (ctx); return GSS_S_COMPLETE; } diff --git a/source4/heimdal/lib/gssapi/display_name.c b/source4/heimdal/lib/gssapi/krb5/display_name.c index 27a232fd3c..8fce7d8572 100644 --- a/source4/heimdal/lib/gssapi/display_name.c +++ b/source4/heimdal/lib/gssapi/krb5/display_name.c @@ -31,28 +31,27 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: display_name.c,v 1.9 2003/03/16 17:46:11 lha Exp $"); +RCSID("$Id: display_name.c,v 1.12 2006/10/07 22:14:31 lha Exp $"); -OM_uint32 gss_display_name +OM_uint32 _gsskrb5_display_name (OM_uint32 * minor_status, const gss_name_t input_name, gss_buffer_t output_name_buffer, gss_OID * output_name_type ) { + krb5_const_principal name = (krb5_const_principal)input_name; krb5_error_code kret; char *buf; size_t len; GSSAPI_KRB5_INIT (); - kret = krb5_unparse_name (gssapi_krb5_context, - input_name, - &buf); + kret = krb5_unparse_name (_gsskrb5_context, name, &buf); if (kret) { *minor_status = kret; - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); return GSS_S_FAILURE; } len = strlen (buf); diff --git a/source4/heimdal/lib/gssapi/display_status.c b/source4/heimdal/lib/gssapi/krb5/display_status.c index 0aa88bb57c..11926ca557 100644 --- a/source4/heimdal/lib/gssapi/display_status.c +++ b/source4/heimdal/lib/gssapi/krb5/display_status.c @@ -31,9 +31,9 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: display_status.c,v 1.14 2005/10/12 07:23:03 lha Exp $"); +RCSID("$Id: display_status.c,v 1.16 2006/10/07 22:14:33 lha Exp $"); static const char * calling_error(OM_uint32 v) @@ -112,9 +112,9 @@ supplementary_error(OM_uint32 v) } void -gssapi_krb5_clear_status (void) +_gsskrb5_clear_status (void) { - struct gssapi_thr_context *ctx = gssapi_get_thread_context(1); + struct gssapi_thr_context *ctx = _gsskrb5_get_thread_context(1); if (ctx == NULL) return; HEIMDAL_MUTEX_lock(&ctx->mutex); @@ -125,9 +125,9 @@ gssapi_krb5_clear_status (void) } void -gssapi_krb5_set_status (const char *fmt, ...) +_gsskrb5_set_status (const char *fmt, ...) { - struct gssapi_thr_context *ctx = gssapi_get_thread_context(1); + struct gssapi_thr_context *ctx = _gsskrb5_get_thread_context(1); va_list args; if (ctx == NULL) @@ -143,22 +143,22 @@ gssapi_krb5_set_status (const char *fmt, ...) } void -gssapi_krb5_set_error_string (void) +_gsskrb5_set_error_string (void) { char *e; - e = krb5_get_error_string(gssapi_krb5_context); + e = krb5_get_error_string(_gsskrb5_context); if (e) { - gssapi_krb5_set_status("%s", e); - krb5_free_error_string(gssapi_krb5_context, e); + _gsskrb5_set_status("%s", e); + krb5_free_error_string(_gsskrb5_context, e); } else - gssapi_krb5_clear_status(); + _gsskrb5_clear_status(); } char * -gssapi_krb5_get_error_string (void) +_gsskrb5_get_error_string (void) { - struct gssapi_thr_context *ctx = gssapi_get_thread_context(0); + struct gssapi_thr_context *ctx = _gsskrb5_get_thread_context(0); char *ret; if (ctx == NULL) @@ -170,7 +170,7 @@ gssapi_krb5_get_error_string (void) return ret; } -OM_uint32 gss_display_status +OM_uint32 _gsskrb5_display_status (OM_uint32 *minor_status, OM_uint32 status_value, int status_type, @@ -200,9 +200,9 @@ OM_uint32 gss_display_status calling_error(GSS_CALLING_ERROR(status_value)), routine_error(GSS_ROUTINE_ERROR(status_value))); } else if (status_type == GSS_C_MECH_CODE) { - buf = gssapi_krb5_get_error_string (); + buf = _gsskrb5_get_error_string (); if (buf == NULL) { - const char *tmp = krb5_get_err_text (gssapi_krb5_context, + const char *tmp = krb5_get_err_text (_gsskrb5_context, status_value); if (tmp == NULL) asprintf(&buf, "unknown mech error-code %u", diff --git a/source4/heimdal/lib/gssapi/duplicate_name.c b/source4/heimdal/lib/gssapi/krb5/duplicate_name.c index 2b54e90ec8..475ae61efc 100644 --- a/source4/heimdal/lib/gssapi/duplicate_name.c +++ b/source4/heimdal/lib/gssapi/krb5/duplicate_name.c @@ -31,26 +31,26 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: duplicate_name.c,v 1.7 2003/03/16 17:44:26 lha Exp $"); +RCSID("$Id: duplicate_name.c,v 1.10 2006/10/07 22:14:35 lha Exp $"); -OM_uint32 gss_duplicate_name ( +OM_uint32 _gsskrb5_duplicate_name ( OM_uint32 * minor_status, const gss_name_t src_name, gss_name_t * dest_name ) { + krb5_const_principal src = (krb5_const_principal)src_name; + krb5_principal *dest = (krb5_principal *)dest_name; krb5_error_code kret; GSSAPI_KRB5_INIT (); - kret = krb5_copy_principal (gssapi_krb5_context, - src_name, - dest_name); + kret = krb5_copy_principal (_gsskrb5_context, src, dest); if (kret) { *minor_status = kret; - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); return GSS_S_FAILURE; } else { *minor_status = 0; diff --git a/source4/heimdal/lib/gssapi/encapsulate.c b/source4/heimdal/lib/gssapi/krb5/encapsulate.c index 4d488a6c42..a015a95103 100644 --- a/source4/heimdal/lib/gssapi/encapsulate.c +++ b/source4/heimdal/lib/gssapi/krb5/encapsulate.c @@ -31,9 +31,9 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: encapsulate.c,v 1.8 2003/09/04 18:08:55 lha Exp $"); +RCSID("$Id: encapsulate.c,v 1.12 2006/10/14 10:02:56 lha Exp $"); void _gssapi_encap_length (size_t data_len, @@ -45,13 +45,13 @@ _gssapi_encap_length (size_t data_len, *len = 1 + 1 + mech->length + data_len; - len_len = length_len(*len); + len_len = der_length_len(*len); *total_len = 1 + len_len + *len; } void -gssapi_krb5_encap_length (size_t data_len, +_gsskrb5_encap_length (size_t data_len, size_t *len, size_t *total_len, const gss_OID mech) @@ -59,28 +59,30 @@ gssapi_krb5_encap_length (size_t data_len, _gssapi_encap_length(data_len + 2, len, total_len, mech); } -u_char * -gssapi_krb5_make_header (u_char *p, +void * +_gsskrb5_make_header (void *ptr, size_t len, - const u_char *type, + const void *type, const gss_OID mech) { + u_char *p = ptr; p = _gssapi_make_mech_header(p, len, mech); memcpy (p, type, 2); p += 2; return p; } -u_char * -_gssapi_make_mech_header(u_char *p, +void * +_gssapi_make_mech_header(void *ptr, size_t len, const gss_OID mech) { + u_char *p = ptr; int e; size_t len_len, foo; *p++ = 0x60; - len_len = length_len(len); + len_len = der_length_len(len); e = der_put_length (p + len_len - 1, len_len, len, &foo); if(e || foo != len_len) abort (); @@ -105,7 +107,7 @@ _gssapi_encapsulate( ) { size_t len, outer_len; - u_char *p; + void *p; _gssapi_encap_length (in_data->length, &len, &outer_len, mech); @@ -127,18 +129,18 @@ _gssapi_encapsulate( */ OM_uint32 -gssapi_krb5_encapsulate( +_gsskrb5_encapsulate( OM_uint32 *minor_status, const krb5_data *in_data, gss_buffer_t output_token, - const u_char *type, + const void *type, const gss_OID mech ) { size_t len, outer_len; u_char *p; - gssapi_krb5_encap_length (in_data->length, &len, &outer_len, mech); + _gsskrb5_encap_length (in_data->length, &len, &outer_len, mech); output_token->length = outer_len; output_token->value = malloc (outer_len); @@ -147,7 +149,7 @@ gssapi_krb5_encapsulate( return GSS_S_FAILURE; } - p = gssapi_krb5_make_header (output_token->value, len, type, mech); + p = _gsskrb5_make_header (output_token->value, len, type, mech); memcpy (p, in_data->data, in_data->length); return GSS_S_COMPLETE; } diff --git a/source4/heimdal/lib/gssapi/krb5/export_name.c b/source4/heimdal/lib/gssapi/krb5/export_name.c new file mode 100644 index 0000000000..d00c458898 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/export_name.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 1997, 1999, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: export_name.c,v 1.8 2006/10/07 22:14:40 lha Exp $"); + +OM_uint32 _gsskrb5_export_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t exported_name + ) +{ + krb5_const_principal princ = (krb5_const_principal)input_name; + krb5_error_code kret; + char *buf, *name; + size_t len; + + GSSAPI_KRB5_INIT (); + kret = krb5_unparse_name (_gsskrb5_context, princ, &name); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } + len = strlen (name); + + exported_name->length = 10 + len + GSS_KRB5_MECHANISM->length; + exported_name->value = malloc(exported_name->length); + if (exported_name->value == NULL) { + free (name); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + /* TOK, MECH_OID_LEN, DER(MECH_OID), NAME_LEN, NAME */ + + buf = exported_name->value; + memcpy(buf, "\x04\x01", 2); + buf += 2; + buf[0] = ((GSS_KRB5_MECHANISM->length + 2) >> 8) & 0xff; + buf[1] = (GSS_KRB5_MECHANISM->length + 2) & 0xff; + buf+= 2; + buf[0] = 0x06; + buf[1] = (GSS_KRB5_MECHANISM->length) & 0xFF; + buf+= 2; + + memcpy(buf, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); + buf += GSS_KRB5_MECHANISM->length; + + buf[0] = (len >> 24) & 0xff; + buf[1] = (len >> 16) & 0xff; + buf[2] = (len >> 8) & 0xff; + buf[3] = (len) & 0xff; + buf += 4; + + memcpy (buf, name, len); + + free (name); + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/export_sec_context.c b/source4/heimdal/lib/gssapi/krb5/export_sec_context.c new file mode 100644 index 0000000000..aff03a0b67 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/export_sec_context.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: export_sec_context.c,v 1.11 2006/10/07 22:14:42 lha Exp $"); + +OM_uint32 +_gsskrb5_export_sec_context ( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t interprocess_token + ) +{ + const gsskrb5_ctx ctx = (const gsskrb5_ctx) *context_handle; + krb5_storage *sp; + krb5_auth_context ac; + OM_uint32 ret = GSS_S_COMPLETE; + krb5_data data; + gss_buffer_desc buffer; + int flags; + OM_uint32 minor; + krb5_error_code kret; + + GSSAPI_KRB5_INIT (); + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (!(ctx->flags & GSS_C_TRANS_FLAG)) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + *minor_status = 0; + return GSS_S_UNAVAILABLE; + } + + sp = krb5_storage_emem (); + if (sp == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + ac = ctx->auth_context; + + /* flagging included fields */ + + flags = 0; + if (ac->local_address) + flags |= SC_LOCAL_ADDRESS; + if (ac->remote_address) + flags |= SC_REMOTE_ADDRESS; + if (ac->keyblock) + flags |= SC_KEYBLOCK; + if (ac->local_subkey) + flags |= SC_LOCAL_SUBKEY; + if (ac->remote_subkey) + flags |= SC_REMOTE_SUBKEY; + + kret = krb5_store_int32 (sp, flags); + if (kret) { + *minor_status = kret; + goto failure; + } + + /* marshall auth context */ + + kret = krb5_store_int32 (sp, ac->flags); + if (kret) { + *minor_status = kret; + goto failure; + } + if (ac->local_address) { + kret = krb5_store_address (sp, *ac->local_address); + if (kret) { + *minor_status = kret; + goto failure; + } + } + if (ac->remote_address) { + kret = krb5_store_address (sp, *ac->remote_address); + if (kret) { + *minor_status = kret; + goto failure; + } + } + kret = krb5_store_int16 (sp, ac->local_port); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int16 (sp, ac->remote_port); + if (kret) { + *minor_status = kret; + goto failure; + } + if (ac->keyblock) { + kret = krb5_store_keyblock (sp, *ac->keyblock); + if (kret) { + *minor_status = kret; + goto failure; + } + } + if (ac->local_subkey) { + kret = krb5_store_keyblock (sp, *ac->local_subkey); + if (kret) { + *minor_status = kret; + goto failure; + } + } + if (ac->remote_subkey) { + kret = krb5_store_keyblock (sp, *ac->remote_subkey); + if (kret) { + *minor_status = kret; + goto failure; + } + } + kret = krb5_store_int32 (sp, ac->local_seqnumber); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ac->remote_seqnumber); + if (kret) { + *minor_status = kret; + goto failure; + } + + kret = krb5_store_int32 (sp, ac->keytype); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ac->cksumtype); + if (kret) { + *minor_status = kret; + goto failure; + } + + /* names */ + + ret = _gsskrb5_export_name (minor_status, + (gss_name_t)ctx->source, &buffer); + if (ret) + goto failure; + data.data = buffer.value; + data.length = buffer.length; + kret = krb5_store_data (sp, data); + _gsskrb5_release_buffer (&minor, &buffer); + if (kret) { + *minor_status = kret; + goto failure; + } + + ret = _gsskrb5_export_name (minor_status, + (gss_name_t)ctx->target, &buffer); + if (ret) + goto failure; + data.data = buffer.value; + data.length = buffer.length; + + ret = GSS_S_FAILURE; + + kret = krb5_store_data (sp, data); + _gsskrb5_release_buffer (&minor, &buffer); + if (kret) { + *minor_status = kret; + goto failure; + } + + kret = krb5_store_int32 (sp, ctx->flags); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ctx->more_flags); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = krb5_store_int32 (sp, ctx->lifetime); + if (kret) { + *minor_status = kret; + goto failure; + } + kret = _gssapi_msg_order_export(sp, ctx->order); + if (kret ) { + *minor_status = kret; + goto failure; + } + + kret = krb5_storage_to_data (sp, &data); + krb5_storage_free (sp); + if (kret) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + *minor_status = kret; + return GSS_S_FAILURE; + } + interprocess_token->length = data.length; + interprocess_token->value = data.data; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + ret = _gsskrb5_delete_sec_context (minor_status, context_handle, + GSS_C_NO_BUFFER); + if (ret != GSS_S_COMPLETE) + _gsskrb5_release_buffer (NULL, interprocess_token); + *minor_status = 0; + return ret; + failure: + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + krb5_storage_free (sp); + return ret; +} diff --git a/source4/heimdal/lib/gssapi/external.c b/source4/heimdal/lib/gssapi/krb5/external.c index f8c1d23f98..7419bc2fe8 100644 --- a/source4/heimdal/lib/gssapi/external.c +++ b/source4/heimdal/lib/gssapi/krb5/external.c @@ -31,9 +31,10 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" +#include <gssapi_mech.h> -RCSID("$Id: external.c,v 1.7 2005/08/23 11:59:47 lha Exp $"); +RCSID("$Id: external.c,v 1.18 2006/10/20 21:50:24 lha Exp $"); /* * The implementation must reserve static storage for a @@ -226,18 +227,6 @@ static gss_OID_desc gss_krb5_mechanism_oid_desc = gss_OID GSS_KRB5_MECHANISM = &gss_krb5_mechanism_oid_desc; /* - * RFC2478, SPNEGO: - * The security mechanism of the initial - * negotiation token is identified by the Object Identifier - * iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2). - */ - -static gss_OID_desc gss_spnego_mechanism_oid_desc = -{6, rk_UNCONST("\x2b\x06\x01\x05\x05\x02")}; - -gss_OID GSS_SPNEGO_MECHANISM = &gss_spnego_mechanism_oid_desc; - -/* * draft-ietf-cat-iakerb-09, IAKERB: * The mechanism ID for IAKERB proxy GSS-API Kerberos, in accordance * with the mechanism proposed by SPNEGO [7] for negotiating protocol @@ -261,7 +250,159 @@ static gss_OID_desc gss_iakerb_min_msg_mechanism_oid_desc = gss_OID GSS_IAKERB_MIN_MSG_MECHANISM = &gss_iakerb_min_msg_mechanism_oid_desc; /* + * + */ + +static gss_OID_desc gss_c_peer_has_updated_spnego_oid_desc = +{9, (void *)"\x2b\x06\x01\x04\x01\xa9\x4a\x13\x05"}; + +gss_OID GSS_C_PEER_HAS_UPDATED_SPNEGO = &gss_c_peer_has_updated_spnego_oid_desc; + +/* + * 1.2.752.43.13 Heimdal GSS-API Extentions + */ + +/* 1.2.752.43.13.1 */ +static gss_OID_desc gss_krb5_copy_ccache_x_oid_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x01")}; + +gss_OID GSS_KRB5_COPY_CCACHE_X = &gss_krb5_copy_ccache_x_oid_desc; + +/* 1.2.752.43.13.2 */ +static gss_OID_desc gss_krb5_get_tkt_flags_x_oid_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x02")}; + +gss_OID GSS_KRB5_GET_TKT_FLAGS_X = &gss_krb5_get_tkt_flags_x_oid_desc; + +/* 1.2.752.43.13.3 */ +static gss_OID_desc gss_krb5_extract_authz_data_from_sec_context_x_oid_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x03")}; + +gss_OID GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X = &gss_krb5_extract_authz_data_from_sec_context_x_oid_desc; + +/* 1.2.752.43.13.4 */ +static gss_OID_desc gss_krb5_compat_des3_mic_x_oid_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x04")}; + +gss_OID GSS_KRB5_COMPAT_DES3_MIC_X = &gss_krb5_compat_des3_mic_x_oid_desc; + +/* 1.2.752.43.13.5 */ +static gss_OID_desc gss_krb5_register_acceptor_identity_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x05")}; + +gss_OID GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X = &gss_krb5_register_acceptor_identity_x_desc; + +/* 1.2.752.43.13.6 */ +static gss_OID_desc gss_krb5_export_lucid_context_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x06")}; + +gss_OID GSS_KRB5_EXPORT_LUCID_CONTEXT_X = &gss_krb5_export_lucid_context_x_desc; + +/* 1.2.752.43.13.6.1 */ +static gss_OID_desc gss_krb5_export_lucid_context_v1_x_desc = +{7, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x06\x01")}; + +gss_OID GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X = &gss_krb5_export_lucid_context_v1_x_desc; + +/* 1.2.752.43.13.7 */ +static gss_OID_desc gss_krb5_set_dns_canonicalize_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x07")}; + +gss_OID GSS_KRB5_SET_DNS_CANONICALIZE_X = &gss_krb5_set_dns_canonicalize_x_desc; + +/* 1.2.752.43.13.8 */ +static gss_OID_desc gss_krb5_get_subkey_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x08")}; + +gss_OID GSS_KRB5_GET_SUBKEY_X = &gss_krb5_get_subkey_x_desc; + +/* 1.2.752.43.13.9 */ +static gss_OID_desc gss_krb5_get_initiator_subkey_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x09")}; + +gss_OID GSS_KRB5_GET_INITIATOR_SUBKEY_X = &gss_krb5_get_initiator_subkey_x_desc; + +/* 1.2.752.43.13.10 */ +static gss_OID_desc gss_krb5_get_acceptor_subkey_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0a")}; + +gss_OID GSS_KRB5_GET_ACCEPTOR_SUBKEY_X = &gss_krb5_get_acceptor_subkey_x_desc; + +/* 1.2.752.43.13.11 */ +static gss_OID_desc gss_krb5_send_to_kdc_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0b")}; + +gss_OID GSS_KRB5_SEND_TO_KDC_X = &gss_krb5_send_to_kdc_x_desc; + +/* 1.2.752.43.13.12 */ +static gss_OID_desc gss_krb5_get_authtime_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0c")}; + +gss_OID GSS_KRB5_GET_AUTHTIME_X = &gss_krb5_get_authtime_x_desc; + +/* 1.2.752.43.13.14 */ +static gss_OID_desc gss_krb5_get_service_keyblock_x_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x0d")}; + +gss_OID GSS_KRB5_GET_SERVICE_KEYBLOCK_X = &gss_krb5_get_service_keyblock_x_desc; + +/* 1.2.752.43.14.1 */ +static gss_OID_desc gss_sasl_digest_md5_mechanism_desc = +{6, rk_UNCONST("\x2a\x85\x70\x2b\x0e\x01") }; + +gss_OID GSS_SASL_DIGEST_MD5_MECHANISM = &gss_sasl_digest_md5_mechanism_desc; + +/* * Context for krb5 calls. */ -krb5_context gssapi_krb5_context; +krb5_context _gsskrb5_context; + +/* + * + */ + +static gssapi_mech_interface_desc krb5_mech = { + GMI_VERSION, + "kerberos 5", + {9, "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" }, + _gsskrb5_acquire_cred, + _gsskrb5_release_cred, + _gsskrb5_init_sec_context, + _gsskrb5_accept_sec_context, + _gsskrb5_process_context_token, + _gsskrb5_delete_sec_context, + _gsskrb5_context_time, + _gsskrb5_get_mic, + _gsskrb5_verify_mic, + _gsskrb5_wrap, + _gsskrb5_unwrap, + _gsskrb5_display_status, + _gsskrb5_indicate_mechs, + _gsskrb5_compare_name, + _gsskrb5_display_name, + _gsskrb5_import_name, + _gsskrb5_export_name, + _gsskrb5_release_name, + _gsskrb5_inquire_cred, + _gsskrb5_inquire_context, + _gsskrb5_wrap_size_limit, + _gsskrb5_add_cred, + _gsskrb5_inquire_cred_by_mech, + _gsskrb5_export_sec_context, + _gsskrb5_import_sec_context, + _gsskrb5_inquire_names_for_mech, + _gsskrb5_inquire_mechs_for_name, + _gsskrb5_canonicalize_name, + _gsskrb5_duplicate_name, + _gsskrb5_inquire_sec_context_by_oid, + _gsskrb5_inquire_cred_by_oid, + _gsskrb5_set_sec_context_option, + _gsskrb5_set_cred_option +}; + +gssapi_mech_interface +__gss_krb5_initialize(void) +{ + return &krb5_mech; +} diff --git a/source4/heimdal/lib/gssapi/get_mic.c b/source4/heimdal/lib/gssapi/krb5/get_mic.c index 76f69cf41c..5a078d634d 100644 --- a/source4/heimdal/lib/gssapi/get_mic.c +++ b/source4/heimdal/lib/gssapi/krb5/get_mic.c @@ -31,14 +31,14 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: get_mic.c,v 1.31 2006/05/08 09:55:37 lha Exp $"); +RCSID("$Id: get_mic.c,v 1.34 2006/10/18 15:59:23 lha Exp $"); static OM_uint32 mic_des (OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx ctx, gss_qop_t qop_req, const gss_buffer_t message_buffer, gss_buffer_t message_token, @@ -54,7 +54,7 @@ mic_des int32_t seq_number; size_t len, total_len; - gssapi_krb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); + _gsskrb5_encap_length (22, &len, &total_len, GSS_KRB5_MECHANISM); message_token->length = total_len; message_token->value = malloc (total_len); @@ -64,7 +64,7 @@ mic_des return GSS_S_FAILURE; } - p = gssapi_krb5_make_header(message_token->value, + p = _gsskrb5_make_header(message_token->value, len, "\x01\x01", /* TOK_ID */ GSS_KRB5_MECHANISM); @@ -92,10 +92,10 @@ mic_des &schedule, &zero); memcpy (p - 8, hash, 8); /* SGN_CKSUM */ - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); /* sequence number */ - krb5_auth_con_getlocalseqnumber (gssapi_krb5_context, - context_handle->auth_context, + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, + ctx->auth_context, &seq_number); p -= 16; /* SND_SEQ */ @@ -104,17 +104,17 @@ mic_des p[2] = (seq_number >> 16) & 0xFF; p[3] = (seq_number >> 24) & 0xFF; memset (p + 4, - (context_handle->more_flags & LOCAL) ? 0 : 0xFF, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, 4); DES_set_key (&deskey, &schedule); DES_cbc_encrypt ((void *)p, (void *)p, 8, &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT); - krb5_auth_con_setlocalseqnumber (gssapi_krb5_context, - context_handle->auth_context, + krb5_auth_con_setlocalseqnumber (_gsskrb5_context, + ctx->auth_context, ++seq_number); - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); memset (deskey, 0, sizeof(deskey)); memset (&schedule, 0, sizeof(schedule)); @@ -126,7 +126,7 @@ mic_des static OM_uint32 mic_des3 (OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx ctx, gss_qop_t qop_req, const gss_buffer_t message_buffer, gss_buffer_t message_token, @@ -146,7 +146,7 @@ mic_des3 char *tmp; char ivec[8]; - gssapi_krb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM); + _gsskrb5_encap_length (36, &len, &total_len, GSS_KRB5_MECHANISM); message_token->length = total_len; message_token->value = malloc (total_len); @@ -156,7 +156,7 @@ mic_des3 return GSS_S_FAILURE; } - p = gssapi_krb5_make_header(message_token->value, + p = _gsskrb5_make_header(message_token->value, len, "\x01\x01", /* TOK-ID */ GSS_KRB5_MECHANISM); @@ -180,18 +180,18 @@ mic_des3 memcpy (tmp, p - 8, 8); memcpy (tmp + 8, message_buffer->value, message_buffer->length); - kret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto); + kret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); if (kret) { free (message_token->value); message_token->value = NULL; message_token->length = 0; free (tmp); - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = kret; return GSS_S_FAILURE; } - kret = krb5_create_checksum (gssapi_krb5_context, + kret = krb5_create_checksum (_gsskrb5_context, crypto, KRB5_KU_USAGE_SIGN, 0, @@ -199,22 +199,22 @@ mic_des3 message_buffer->length + 8, &cksum); free (tmp); - krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_crypto_destroy (_gsskrb5_context, crypto); if (kret) { free (message_token->value); message_token->value = NULL; message_token->length = 0; - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = kret; return GSS_S_FAILURE; } memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); /* sequence number */ - krb5_auth_con_getlocalseqnumber (gssapi_krb5_context, - context_handle->auth_context, + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, + ctx->auth_context, &seq_number); seq[0] = (seq_number >> 0) & 0xFF; @@ -222,35 +222,35 @@ mic_des3 seq[2] = (seq_number >> 16) & 0xFF; seq[3] = (seq_number >> 24) & 0xFF; memset (seq + 4, - (context_handle->more_flags & LOCAL) ? 0 : 0xFF, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, 4); - kret = krb5_crypto_init(gssapi_krb5_context, key, + kret = krb5_crypto_init(_gsskrb5_context, key, ETYPE_DES3_CBC_NONE, &crypto); if (kret) { free (message_token->value); message_token->value = NULL; message_token->length = 0; - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = kret; return GSS_S_FAILURE; } - if (context_handle->more_flags & COMPAT_OLD_DES3) + if (ctx->more_flags & COMPAT_OLD_DES3) memset(ivec, 0, 8); else memcpy(ivec, p + 8, 8); - kret = krb5_encrypt_ivec (gssapi_krb5_context, + kret = krb5_encrypt_ivec (_gsskrb5_context, crypto, KRB5_KU_USAGE_SEQ, seq, 8, &encdata, ivec); - krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_crypto_destroy (_gsskrb5_context, crypto); if (kret) { free (message_token->value); message_token->value = NULL; message_token->length = 0; - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = kret; return GSS_S_FAILURE; } @@ -260,17 +260,17 @@ mic_des3 memcpy (p, encdata.data, encdata.length); krb5_data_free (&encdata); - krb5_auth_con_setlocalseqnumber (gssapi_krb5_context, - context_handle->auth_context, + krb5_auth_con_setlocalseqnumber (_gsskrb5_context, + ctx->auth_context, ++seq_number); - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); free_Checksum (&cksum); *minor_status = 0; return GSS_S_COMPLETE; } -OM_uint32 gss_get_mic +OM_uint32 _gsskrb5_get_mic (OM_uint32 * minor_status, const gss_ctx_id_t context_handle, gss_qop_t qop_req, @@ -278,37 +278,40 @@ OM_uint32 gss_get_mic gss_buffer_t message_token ) { + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; krb5_keyblock *key; OM_uint32 ret; krb5_keytype keytype; - ret = gss_krb5_get_subkey(context_handle, &key); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; return GSS_S_FAILURE; } - krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype); + krb5_enctype_to_keytype (_gsskrb5_context, key->keytype, &keytype); switch (keytype) { case KEYTYPE_DES : - ret = mic_des (minor_status, context_handle, qop_req, + ret = mic_des (minor_status, ctx, qop_req, message_buffer, message_token, key); break; case KEYTYPE_DES3 : - ret = mic_des3 (minor_status, context_handle, qop_req, + ret = mic_des3 (minor_status, ctx, qop_req, message_buffer, message_token, key); break; case KEYTYPE_ARCFOUR: case KEYTYPE_ARCFOUR_56: - ret = _gssapi_get_mic_arcfour (minor_status, context_handle, qop_req, + ret = _gssapi_get_mic_arcfour (minor_status, ctx, qop_req, message_buffer, message_token, key); break; default : - ret = _gssapi_mic_cfx (minor_status, context_handle, qop_req, + ret = _gssapi_mic_cfx (minor_status, ctx, qop_req, message_buffer, message_token, key); break; } - krb5_free_keyblock (gssapi_krb5_context, key); + krb5_free_keyblock (_gsskrb5_context, key); return ret; } diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h new file mode 100644 index 0000000000..426c0ab200 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/gsskrb5-private.h @@ -0,0 +1,705 @@ +/* This is a generated file */ +#ifndef __gsskrb5_private_h__ +#define __gsskrb5_private_h__ + +#include <stdarg.h> + +gssapi_mech_interface +__gss_krb5_initialize (void); + +OM_uint32 +__gsskrb5_ccache_lifetime ( + OM_uint32 */*minor_status*/, + krb5_ccache /*id*/, + krb5_principal /*principal*/, + OM_uint32 */*lifetime*/); + +OM_uint32 +_gss_DES3_get_mic_compat ( + OM_uint32 */*minor_status*/, + gsskrb5_ctx /*ctx*/); + +OM_uint32 +_gssapi_decapsulate ( + OM_uint32 */*minor_status*/, + gss_buffer_t /*input_token_buffer*/, + krb5_data */*out_data*/, + const gss_OID mech ); + +void +_gssapi_encap_length ( + size_t /*data_len*/, + size_t */*len*/, + size_t */*total_len*/, + const gss_OID /*mech*/); + +OM_uint32 +_gssapi_encapsulate ( + OM_uint32 */*minor_status*/, + const krb5_data */*in_data*/, + gss_buffer_t /*output_token*/, + const gss_OID mech ); + +OM_uint32 +_gssapi_get_mic_arcfour ( + OM_uint32 * /*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*message_buffer*/, + gss_buffer_t /*message_token*/, + krb5_keyblock */*key*/); + +void * +_gssapi_make_mech_header ( + void */*ptr*/, + size_t /*len*/, + const gss_OID /*mech*/); + +OM_uint32 +_gssapi_mic_cfx ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*message_buffer*/, + gss_buffer_t /*message_token*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_msg_order_check ( + struct gss_msg_order */*o*/, + OM_uint32 /*seq_num*/); + +OM_uint32 +_gssapi_msg_order_create ( + OM_uint32 */*minor_status*/, + struct gss_msg_order **/*o*/, + OM_uint32 /*flags*/, + OM_uint32 /*seq_num*/, + OM_uint32 /*jitter_window*/, + int /*use_64*/); + +OM_uint32 +_gssapi_msg_order_destroy (struct gss_msg_order **/*m*/); + +krb5_error_code +_gssapi_msg_order_export ( + krb5_storage */*sp*/, + struct gss_msg_order */*o*/); + +OM_uint32 +_gssapi_msg_order_f (OM_uint32 /*flags*/); + +OM_uint32 +_gssapi_msg_order_import ( + OM_uint32 */*minor_status*/, + krb5_storage */*sp*/, + struct gss_msg_order **/*o*/); + +OM_uint32 +_gssapi_unwrap_arcfour ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + const gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int */*conf_state*/, + gss_qop_t */*qop_state*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_unwrap_cfx ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + const gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int */*conf_state*/, + gss_qop_t */*qop_state*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_verify_mech_header ( + u_char **/*str*/, + size_t /*total_len*/, + gss_OID /*mech*/); + +OM_uint32 +_gssapi_verify_mic_arcfour ( + OM_uint32 * /*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t * /*qop_state*/, + krb5_keyblock */*key*/, + char */*type*/); + +OM_uint32 +_gssapi_verify_mic_cfx ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t */*qop_state*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_verify_pad ( + gss_buffer_t /*wrapped_token*/, + size_t /*datalen*/, + size_t */*padlen*/); + +OM_uint32 +_gssapi_wrap_arcfour ( + OM_uint32 * /*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t /*output_message_buffer*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_wrap_cfx ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*input_message_buffer*/, + int */*conf_state*/, + gss_buffer_t /*output_message_buffer*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_wrap_size_arcfour ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*ctx*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + OM_uint32 /*req_output_size*/, + OM_uint32 */*max_input_size*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gssapi_wrap_size_cfx ( + OM_uint32 */*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + OM_uint32 /*req_output_size*/, + OM_uint32 */*max_input_size*/, + krb5_keyblock */*key*/); + +OM_uint32 +_gsskrb5_accept_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + const gss_cred_id_t /*acceptor_cred_handle*/, + const gss_buffer_t /*input_token_buffer*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + gss_name_t * /*src_name*/, + gss_OID * /*mech_type*/, + gss_buffer_t /*output_token*/, + OM_uint32 * /*ret_flags*/, + OM_uint32 * /*time_rec*/, + gss_cred_id_t * /*delegated_cred_handle*/); + +OM_uint32 +_gsskrb5_acquire_cred ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*desired_name*/, + OM_uint32 /*time_req*/, + const gss_OID_set /*desired_mechs*/, + gss_cred_usage_t /*cred_usage*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * time_rec ); + +OM_uint32 +_gsskrb5_add_cred ( + OM_uint32 */*minor_status*/, + const gss_cred_id_t /*input_cred_handle*/, + const gss_name_t /*desired_name*/, + const gss_OID /*desired_mech*/, + gss_cred_usage_t /*cred_usage*/, + OM_uint32 /*initiator_time_req*/, + OM_uint32 /*acceptor_time_req*/, + gss_cred_id_t */*output_cred_handle*/, + gss_OID_set */*actual_mechs*/, + OM_uint32 */*initiator_time_rec*/, + OM_uint32 */*acceptor_time_rec*/); + +OM_uint32 +_gsskrb5_add_oid_set_member ( + OM_uint32 * /*minor_status*/, + const gss_OID /*member_oid*/, + gss_OID_set * oid_set ); + +OM_uint32 +_gsskrb5_canonicalize_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + const gss_OID /*mech_type*/, + gss_name_t * output_name ); + +void +_gsskrb5_clear_status (void); + +OM_uint32 +_gsskrb5_compare_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*name1*/, + const gss_name_t /*name2*/, + int * name_equal ); + +OM_uint32 +_gsskrb5_context_time ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + OM_uint32 * time_rec ); + +OM_uint32 +_gsskrb5_create_8003_checksum ( + OM_uint32 */*minor_status*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + OM_uint32 /*flags*/, + const krb5_data */*fwd_data*/, + Checksum */*result*/); + +OM_uint32 +_gsskrb5_create_ctx ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + enum gss_ctx_id_t_state /*state*/); + +OM_uint32 +_gsskrb5_create_empty_oid_set ( + OM_uint32 * /*minor_status*/, + gss_OID_set * oid_set ); + +OM_uint32 +_gsskrb5_decapsulate ( + OM_uint32 */*minor_status*/, + gss_buffer_t /*input_token_buffer*/, + krb5_data */*out_data*/, + const void */*type*/, + gss_OID /*oid*/); + +krb5_error_code +_gsskrb5_decode_be_om_uint32 ( + const void */*ptr*/, + OM_uint32 */*n*/); + +krb5_error_code +_gsskrb5_decode_om_uint32 ( + const void */*ptr*/, + OM_uint32 */*n*/); + +OM_uint32 +_gsskrb5_delete_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + gss_buffer_t /*output_token*/); + +OM_uint32 +_gsskrb5_display_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_buffer_t /*output_name_buffer*/, + gss_OID * output_name_type ); + +OM_uint32 +_gsskrb5_display_status ( + OM_uint32 */*minor_status*/, + OM_uint32 /*status_value*/, + int /*status_type*/, + const gss_OID /*mech_type*/, + OM_uint32 */*message_context*/, + gss_buffer_t /*status_string*/); + +OM_uint32 +_gsskrb5_duplicate_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*src_name*/, + gss_name_t * dest_name ); + +void +_gsskrb5_encap_length ( + size_t /*data_len*/, + size_t */*len*/, + size_t */*total_len*/, + const gss_OID /*mech*/); + +OM_uint32 +_gsskrb5_encapsulate ( + OM_uint32 */*minor_status*/, + const krb5_data */*in_data*/, + gss_buffer_t /*output_token*/, + const void */*type*/, + const gss_OID mech ); + +krb5_error_code +_gsskrb5_encode_be_om_uint32 ( + OM_uint32 /*n*/, + u_char */*p*/); + +krb5_error_code +_gsskrb5_encode_om_uint32 ( + OM_uint32 /*n*/, + u_char */*p*/); + +OM_uint32 +_gsskrb5_export_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_buffer_t exported_name ); + +OM_uint32 +_gsskrb5_export_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + gss_buffer_t interprocess_token ); + +char * +_gsskrb5_get_error_string (void); + +ssize_t +_gsskrb5_get_mech ( + const u_char */*ptr*/, + size_t /*total_len*/, + const u_char **/*mech_ret*/); + +OM_uint32 +_gsskrb5_get_mic ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*message_buffer*/, + gss_buffer_t message_token ); + +struct gssapi_thr_context * +_gsskrb5_get_thread_context (int /*createp*/); + +OM_uint32 +_gsskrb5_get_tkt_flags ( + OM_uint32 */*minor_status*/, + gsskrb5_ctx /*ctx*/, + OM_uint32 */*tkt_flags*/); + +OM_uint32 +_gsskrb5_import_cred ( + OM_uint32 */*minor_status*/, + krb5_ccache /*id*/, + krb5_principal /*keytab_principal*/, + krb5_keytab /*keytab*/, + gss_cred_id_t */*cred*/); + +OM_uint32 +_gsskrb5_import_name ( + OM_uint32 * /*minor_status*/, + const gss_buffer_t /*input_name_buffer*/, + const gss_OID /*input_name_type*/, + gss_name_t * output_name ); + +OM_uint32 +_gsskrb5_import_sec_context ( + OM_uint32 * /*minor_status*/, + const gss_buffer_t /*interprocess_token*/, + gss_ctx_id_t * context_handle ); + +OM_uint32 +_gsskrb5_indicate_mechs ( + OM_uint32 * /*minor_status*/, + gss_OID_set * mech_set ); + +krb5_error_code +_gsskrb5_init (void); + +OM_uint32 +_gsskrb5_init_sec_context ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*initiator_cred_handle*/, + gss_ctx_id_t * /*context_handle*/, + const gss_name_t /*target_name*/, + const gss_OID /*mech_type*/, + OM_uint32 /*req_flags*/, + OM_uint32 /*time_req*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + const gss_buffer_t /*input_token*/, + gss_OID * /*actual_mech_type*/, + gss_buffer_t /*output_token*/, + OM_uint32 * /*ret_flags*/, + OM_uint32 * time_rec ); + +OM_uint32 +_gsskrb5_inquire_context ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + gss_name_t * /*src_name*/, + gss_name_t * /*targ_name*/, + OM_uint32 * /*lifetime_rec*/, + gss_OID * /*mech_type*/, + OM_uint32 * /*ctx_flags*/, + int * /*locally_initiated*/, + int * open_context ); + +OM_uint32 +_gsskrb5_inquire_cred ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + gss_name_t * /*output_name*/, + OM_uint32 * /*lifetime*/, + gss_cred_usage_t * /*cred_usage*/, + gss_OID_set * mechanisms ); + +OM_uint32 +_gsskrb5_inquire_cred_by_mech ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + const gss_OID /*mech_type*/, + gss_name_t * /*name*/, + OM_uint32 * /*initiator_lifetime*/, + OM_uint32 * /*acceptor_lifetime*/, + gss_cred_usage_t * cred_usage ); + +OM_uint32 +_gsskrb5_inquire_cred_by_oid ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t */*data_set*/); + +OM_uint32 +_gsskrb5_inquire_mechs_for_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_OID_set * mech_types ); + +OM_uint32 +_gsskrb5_inquire_names_for_mech ( + OM_uint32 * /*minor_status*/, + const gss_OID /*mechanism*/, + gss_OID_set * name_types ); + +OM_uint32 +_gsskrb5_inquire_sec_context_by_oid ( + OM_uint32 */*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t */*data_set*/); + +OM_uint32 +_gsskrb5_krb5_ccache_name ( + OM_uint32 */*minor_status*/, + const char */*name*/, + const char **/*out_name*/); + +OM_uint32 +_gsskrb5_lifetime_left ( + OM_uint32 */*minor_status*/, + OM_uint32 /*lifetime*/, + OM_uint32 */*lifetime_rec*/); + +void * +_gsskrb5_make_header ( + void */*ptr*/, + size_t /*len*/, + const void */*type*/, + const gss_OID /*mech*/); + +OM_uint32 +_gsskrb5_process_context_token ( + OM_uint32 */*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t token_buffer ); + +OM_uint32 +_gsskrb5_register_acceptor_identity (const char */*identity*/); + +OM_uint32 +_gsskrb5_release_buffer ( + OM_uint32 * /*minor_status*/, + gss_buffer_t buffer ); + +OM_uint32 +_gsskrb5_release_cred ( + OM_uint32 * /*minor_status*/, + gss_cred_id_t * cred_handle ); + +OM_uint32 +_gsskrb5_release_name ( + OM_uint32 * /*minor_status*/, + gss_name_t * input_name ); + +OM_uint32 +_gsskrb5_release_oid_set ( + OM_uint32 * /*minor_status*/, + gss_OID_set * set ); + +OM_uint32 +_gsskrb5_seal ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + int /*qop_req*/, + gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t output_message_buffer ); + +OM_uint32 +_gsskrb5_set_cred_option ( + OM_uint32 */*minor_status*/, + gss_cred_id_t */*cred_handle*/, + const gss_OID /*desired_object*/, + const gss_buffer_t /*value*/); + +void +_gsskrb5_set_error_string (void); + +OM_uint32 +_gsskrb5_set_sec_context_option ( + OM_uint32 */*minor_status*/, + gss_ctx_id_t */*context_handle*/, + const gss_OID /*desired_object*/, + const gss_buffer_t /*value*/); + +void +_gsskrb5_set_status ( + const char */*fmt*/, + ...); + +OM_uint32 +_gsskrb5_sign ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*qop_req*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t message_token ); + +OM_uint32 +_gsskrb5_test_oid_set_member ( + OM_uint32 * /*minor_status*/, + const gss_OID /*member*/, + const gss_OID_set /*set*/, + int * present ); + +OM_uint32 +_gsskrb5_unseal ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + int * qop_state ); + +OM_uint32 +_gsskrb5_unwrap ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + gss_qop_t * qop_state ); + +OM_uint32 +_gsskrb5_verify ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t /*token_buffer*/, + int * qop_state ); + +OM_uint32 +_gsskrb5_verify_8003_checksum ( + OM_uint32 */*minor_status*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + const Checksum */*cksum*/, + OM_uint32 */*flags*/, + krb5_data */*fwd_data*/); + +OM_uint32 +_gsskrb5_verify_header ( + u_char **/*str*/, + size_t /*total_len*/, + const void */*type*/, + gss_OID /*oid*/); + +OM_uint32 +_gsskrb5_verify_mic ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t * qop_state ); + +OM_uint32 +_gsskrb5_verify_mic_internal ( + OM_uint32 * /*minor_status*/, + const gsskrb5_ctx /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t * /*qop_state*/, + char * type ); + +OM_uint32 +_gsskrb5_wrap ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t output_message_buffer ); + +OM_uint32 +_gsskrb5_wrap_size_limit ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + OM_uint32 /*req_output_size*/, + OM_uint32 * max_input_size ); + +krb5_error_code +_gsskrb5cfx_max_wrap_length_cfx ( + krb5_crypto /*crypto*/, + int /*conf_req_flag*/, + size_t /*input_length*/, + OM_uint32 */*output_length*/); + +krb5_error_code +_gsskrb5cfx_wrap_length_cfx ( + krb5_crypto /*crypto*/, + int /*conf_req_flag*/, + size_t /*input_length*/, + size_t */*output_length*/, + size_t */*cksumsize*/, + uint16_t */*padlength*/); + +krb5_error_code +_gsskrb5i_address_to_krb5addr ( + OM_uint32 /*gss_addr_type*/, + gss_buffer_desc */*gss_addr*/, + int16_t /*port*/, + krb5_address */*address*/); + +krb5_error_code +_gsskrb5i_get_acceptor_subkey ( + const gsskrb5_ctx /*ctx*/, + krb5_keyblock **/*key*/); + +krb5_error_code +_gsskrb5i_get_initiator_subkey ( + const gsskrb5_ctx /*ctx*/, + krb5_keyblock **/*key*/); + +OM_uint32 +_gsskrb5i_get_token_key ( + const gsskrb5_ctx /*ctx*/, + krb5_keyblock **/*key*/); + +void +_gsskrb5i_is_cfx ( + gsskrb5_ctx /*ctx*/, + int */*is_cfx*/); + +#endif /* __gsskrb5_private_h__ */ diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h new file mode 100644 index 0000000000..4d814032c3 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: gsskrb5_locl.h,v 1.6 2006/10/07 22:14:49 lha Exp $ */ + +#ifndef GSSKRB5_LOCL_H +#define GSSKRB5_LOCL_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <krb5_locl.h> +#include <gssapi.h> +#include <gssapi_mech.h> +#include <assert.h> + +#include "cfx.h" + +/* + * + */ + +struct gss_msg_order; + +typedef struct { + struct krb5_auth_context_data *auth_context; + krb5_principal source, target; + OM_uint32 flags; + enum { LOCAL = 1, OPEN = 2, + COMPAT_OLD_DES3 = 4, + COMPAT_OLD_DES3_SELECTED = 8, + ACCEPTOR_SUBKEY = 16 + } more_flags; + enum gss_ctx_id_t_state { + /* initiator states */ + INITIATOR_START, + INITIATOR_WAIT_FOR_MUTAL, + INITIATOR_READY, + /* acceptor states */ + ACCEPTOR_START, + ACCEPTOR_WAIT_FOR_DCESTYLE, + ACCEPTOR_READY + } state; + struct krb5_ticket *ticket; + OM_uint32 lifetime; + HEIMDAL_MUTEX ctx_id_mutex; + struct gss_msg_order *order; + krb5_keyblock *service_keyblock; + krb5_data fwd_data; +} *gsskrb5_ctx; + +typedef struct { + krb5_principal principal; + int cred_flags; +#define GSS_CF_DESTROY_CRED_ON_RELEASE 1 + struct krb5_keytab_data *keytab; + OM_uint32 lifetime; + gss_cred_usage_t usage; + gss_OID_set mechanisms; + struct krb5_ccache_data *ccache; + HEIMDAL_MUTEX cred_id_mutex; +} *gsskrb5_cred; + +typedef struct Principal *gsskrb5_name; + +/* + * + */ + +extern krb5_context _gsskrb5_context; + +extern krb5_keytab _gsskrb5_keytab; +extern HEIMDAL_MUTEX gssapi_keytab_mutex; + +struct gssapi_thr_context { + HEIMDAL_MUTEX mutex; + char *error_string; +}; + +/* + * Prototypes + */ + +#include <krb5/gsskrb5-private.h> + +#define GSSAPI_KRB5_INIT() do { \ + krb5_error_code kret_gss_init; \ + if((kret_gss_init = _gsskrb5_init ()) != 0) { \ + *minor_status = kret_gss_init; \ + return GSS_S_FAILURE; \ + } \ +} while (0) + +/* sec_context flags */ + +#define SC_LOCAL_ADDRESS 0x01 +#define SC_REMOTE_ADDRESS 0x02 +#define SC_KEYBLOCK 0x04 +#define SC_LOCAL_SUBKEY 0x08 +#define SC_REMOTE_SUBKEY 0x10 + +#endif diff --git a/source4/heimdal/lib/gssapi/import_name.c b/source4/heimdal/lib/gssapi/krb5/import_name.c index d393aa1a51..dc24ed5cf2 100644 --- a/source4/heimdal/lib/gssapi/import_name.c +++ b/source4/heimdal/lib/gssapi/krb5/import_name.c @@ -31,30 +31,31 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: import_name.c,v 1.14 2006/02/15 11:59:10 lha Exp $"); +RCSID("$Id: import_name.c,v 1.17 2006/10/07 22:14:51 lha Exp $"); static OM_uint32 parse_krb5_name (OM_uint32 *minor_status, const char *name, gss_name_t *output_name) { + krb5_principal princ; krb5_error_code kerr; - kerr = krb5_parse_name (gssapi_krb5_context, name, output_name); + kerr = krb5_parse_name (_gsskrb5_context, name, &princ); - if (kerr == 0) + if (kerr == 0) { + *output_name = (gss_name_t)princ; return GSS_S_COMPLETE; - else if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) { - gssapi_krb5_set_error_string (); - *minor_status = kerr; - return GSS_S_BAD_NAME; - } else { - gssapi_krb5_set_error_string (); - *minor_status = kerr; - return GSS_S_FAILURE; } + _gsskrb5_set_error_string (); + *minor_status = kerr; + + if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) + return GSS_S_BAD_NAME; + + return GSS_S_FAILURE; } static OM_uint32 @@ -91,8 +92,7 @@ import_hostbased_name (OM_uint32 *minor_status, char *p; char *host; char local_hostname[MAXHOSTNAMELEN]; - - *output_name = NULL; + krb5_principal princ = NULL; tmp = malloc (input_name_buffer->length + 1); if (tmp == NULL) { @@ -117,24 +117,24 @@ import_hostbased_name (OM_uint32 *minor_status, host = local_hostname; } - kerr = krb5_sname_to_principal (gssapi_krb5_context, + kerr = krb5_sname_to_principal (_gsskrb5_context, host, tmp, KRB5_NT_SRV_HST, - output_name); + &princ); free (tmp); *minor_status = kerr; - if (kerr == 0) + if (kerr == 0) { + *output_name = (gss_name_t)princ; return GSS_S_COMPLETE; - else if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) { - gssapi_krb5_set_error_string (); + } + _gsskrb5_set_error_string (); *minor_status = kerr; + + if (kerr == KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) return GSS_S_BAD_NAME; - } else { - gssapi_krb5_set_error_string (); - *minor_status = kerr; - return GSS_S_FAILURE; - } + + return GSS_S_FAILURE; } static OM_uint32 @@ -184,18 +184,7 @@ import_export_name (OM_uint32 *minor_status, return ret; } -int -gss_oid_equal(const gss_OID a, const gss_OID b) -{ - if (a == b) - return 1; - else if (a == GSS_C_NO_OID || b == GSS_C_NO_OID || a->length != b->length) - return 0; - else - return memcmp(a->elements, b->elements, a->length) == 0; -} - -OM_uint32 gss_import_name +OM_uint32 _gsskrb5_import_name (OM_uint32 * minor_status, const gss_buffer_t input_name_buffer, const gss_OID input_name_type, diff --git a/source4/heimdal/lib/gssapi/krb5/import_sec_context.c b/source4/heimdal/lib/gssapi/krb5/import_sec_context.c new file mode 100644 index 0000000000..8131e2621d --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/import_sec_context.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1999 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: import_sec_context.c,v 1.17 2006/10/07 22:14:53 lha Exp $"); + +OM_uint32 +_gsskrb5_import_sec_context ( + OM_uint32 * minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t * context_handle + ) +{ + OM_uint32 ret = GSS_S_FAILURE; + krb5_error_code kret; + krb5_storage *sp; + krb5_auth_context ac; + krb5_address local, remote; + krb5_address *localp, *remotep; + krb5_data data; + gss_buffer_desc buffer; + krb5_keyblock keyblock; + int32_t tmp; + int32_t flags; + gsskrb5_ctx ctx; + gss_name_t name; + + GSSAPI_KRB5_INIT (); + + *context_handle = GSS_C_NO_CONTEXT; + + localp = remotep = NULL; + + sp = krb5_storage_from_mem (interprocess_token->value, + interprocess_token->length); + if (sp == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + krb5_storage_free (sp); + return GSS_S_FAILURE; + } + HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + + kret = krb5_auth_con_init (_gsskrb5_context, + &ctx->auth_context); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + /* flags */ + + *minor_status = 0; + + if (krb5_ret_int32 (sp, &flags) != 0) + goto failure; + + /* retrieve the auth context */ + + ac = ctx->auth_context; + if (krb5_ret_uint32 (sp, &ac->flags) != 0) + goto failure; + if (flags & SC_LOCAL_ADDRESS) { + if (krb5_ret_address (sp, localp = &local) != 0) + goto failure; + } + + if (flags & SC_REMOTE_ADDRESS) { + if (krb5_ret_address (sp, remotep = &remote) != 0) + goto failure; + } + + krb5_auth_con_setaddrs (_gsskrb5_context, ac, localp, remotep); + if (localp) + krb5_free_address (_gsskrb5_context, localp); + if (remotep) + krb5_free_address (_gsskrb5_context, remotep); + localp = remotep = NULL; + + if (krb5_ret_int16 (sp, &ac->local_port) != 0) + goto failure; + + if (krb5_ret_int16 (sp, &ac->remote_port) != 0) + goto failure; + if (flags & SC_KEYBLOCK) { + if (krb5_ret_keyblock (sp, &keyblock) != 0) + goto failure; + krb5_auth_con_setkey (_gsskrb5_context, ac, &keyblock); + krb5_free_keyblock_contents (_gsskrb5_context, &keyblock); + } + if (flags & SC_LOCAL_SUBKEY) { + if (krb5_ret_keyblock (sp, &keyblock) != 0) + goto failure; + krb5_auth_con_setlocalsubkey (_gsskrb5_context, ac, &keyblock); + krb5_free_keyblock_contents (_gsskrb5_context, &keyblock); + } + if (flags & SC_REMOTE_SUBKEY) { + if (krb5_ret_keyblock (sp, &keyblock) != 0) + goto failure; + krb5_auth_con_setremotesubkey (_gsskrb5_context, ac, &keyblock); + krb5_free_keyblock_contents (_gsskrb5_context, &keyblock); + } + if (krb5_ret_uint32 (sp, &ac->local_seqnumber)) + goto failure; + if (krb5_ret_uint32 (sp, &ac->remote_seqnumber)) + goto failure; + + if (krb5_ret_int32 (sp, &tmp) != 0) + goto failure; + ac->keytype = tmp; + if (krb5_ret_int32 (sp, &tmp) != 0) + goto failure; + ac->cksumtype = tmp; + + /* names */ + + if (krb5_ret_data (sp, &data)) + goto failure; + buffer.value = data.data; + buffer.length = data.length; + + ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME, + &name); + if (ret) { + ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID, + &name); + if (ret) { + krb5_data_free (&data); + goto failure; + } + } + ctx->source = (krb5_principal)name; + krb5_data_free (&data); + + if (krb5_ret_data (sp, &data) != 0) + goto failure; + buffer.value = data.data; + buffer.length = data.length; + + ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NT_EXPORT_NAME, + &name); + if (ret) { + ret = _gsskrb5_import_name (minor_status, &buffer, GSS_C_NO_OID, + &name); + if (ret) { + krb5_data_free (&data); + goto failure; + } + } + ctx->target = (krb5_principal)name; + krb5_data_free (&data); + + if (krb5_ret_int32 (sp, &tmp)) + goto failure; + ctx->flags = tmp; + if (krb5_ret_int32 (sp, &tmp)) + goto failure; + ctx->more_flags = tmp; + if (krb5_ret_int32 (sp, &tmp)) + goto failure; + ctx->lifetime = tmp; + + ret = _gssapi_msg_order_import(minor_status, sp, &ctx->order); + if (ret) + goto failure; + + krb5_storage_free (sp); + + *context_handle = (gss_ctx_id_t)ctx; + + return GSS_S_COMPLETE; + +failure: + krb5_auth_con_free (_gsskrb5_context, + ctx->auth_context); + if (ctx->source != NULL) + krb5_free_principal(_gsskrb5_context, ctx->source); + if (ctx->target != NULL) + krb5_free_principal(_gsskrb5_context, ctx->target); + if (localp) + krb5_free_address (_gsskrb5_context, localp); + if (remotep) + krb5_free_address (_gsskrb5_context, remotep); + if(ctx->order) + _gssapi_msg_order_destroy(&ctx->order); + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + krb5_storage_free (sp); + free (ctx); + *context_handle = GSS_C_NO_CONTEXT; + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c b/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c new file mode 100644 index 0000000000..3827533219 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: indicate_mechs.c,v 1.9 2006/10/07 22:14:56 lha Exp $"); + +OM_uint32 _gsskrb5_indicate_mechs + (OM_uint32 * minor_status, + gss_OID_set * mech_set + ) +{ + OM_uint32 ret, junk; + + ret = _gsskrb5_create_empty_oid_set(minor_status, mech_set); + if (ret) + return ret; + + ret = _gsskrb5_add_oid_set_member(minor_status, + GSS_KRB5_MECHANISM, mech_set); + if (ret) { + _gsskrb5_release_oid_set(&junk, mech_set); + return ret; + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/init.c b/source4/heimdal/lib/gssapi/krb5/init.c index 11d7c9bb9f..cbef8740b7 100644 --- a/source4/heimdal/lib/gssapi/init.c +++ b/source4/heimdal/lib/gssapi/krb5/init.c @@ -31,15 +31,11 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: init.c,v 1.7 2003/07/22 19:50:11 lha Exp $"); +RCSID("$Id: init.c,v 1.9 2006/10/07 22:14:58 lha Exp $"); -#ifdef _SAMBA_BUILD_ -#include "auth/kerberos/krb5_init_context.h" -#endif - -static HEIMDAL_MUTEX gssapi_krb5_context_mutex = HEIMDAL_MUTEX_INITIALIZER; +static HEIMDAL_MUTEX _gsskrb5_context_mutex = HEIMDAL_MUTEX_INITIALIZER; static int created_key; static HEIMDAL_thread_key gssapi_context_key; @@ -58,12 +54,12 @@ gssapi_destroy_thread_context(void *ptr) struct gssapi_thr_context * -gssapi_get_thread_context(int createp) +_gsskrb5_get_thread_context(int createp) { struct gssapi_thr_context *ctx; int ret; - HEIMDAL_MUTEX_lock(&gssapi_krb5_context_mutex); + HEIMDAL_MUTEX_lock(&_gsskrb5_context_mutex); if (!created_key) abort(); @@ -80,72 +76,36 @@ gssapi_get_thread_context(int createp) if (ret) goto fail; } - HEIMDAL_MUTEX_unlock(&gssapi_krb5_context_mutex); + HEIMDAL_MUTEX_unlock(&_gsskrb5_context_mutex); return ctx; fail: - HEIMDAL_MUTEX_unlock(&gssapi_krb5_context_mutex); + HEIMDAL_MUTEX_unlock(&_gsskrb5_context_mutex); if (ctx) free(ctx); return NULL; } -#ifdef _SAMBA_BUILD_ -/* Init krb5 with an event context. Disgusting Samba-specific hack */ - -krb5_error_code -gssapi_krb5_init_ev (void *event_context) +krb5_error_code +_gsskrb5_init (void) { - static struct smb_krb5_context *smb_krb5_context; krb5_error_code ret = 0; - HEIMDAL_MUTEX_lock(&gssapi_krb5_context_mutex); + HEIMDAL_MUTEX_lock(&_gsskrb5_context_mutex); - if(smb_krb5_context == NULL) { - ret = smb_krb5_init_context(event_context, &smb_krb5_context); - } + if(_gsskrb5_context == NULL) + ret = krb5_init_context (&_gsskrb5_context); if (ret == 0 && !created_key) { HEIMDAL_key_create(&gssapi_context_key, gssapi_destroy_thread_context, ret); if (ret) { - smb_krb5_free_context(smb_krb5_context); - smb_krb5_context = NULL; + krb5_free_context(_gsskrb5_context); + _gsskrb5_context = NULL; } else created_key = 1; } - if (ret == 0) { - gssapi_krb5_context = smb_krb5_context->krb5_context; - } - HEIMDAL_MUTEX_unlock(&gssapi_krb5_context_mutex); - return ret; -} -#endif - -krb5_error_code -gssapi_krb5_init (void) -{ - krb5_error_code ret = 0; -#ifdef _SAMBA_BUILD_ - ret = gssapi_krb5_init_ev(NULL); -#else - HEIMDAL_MUTEX_lock(&gssapi_krb5_context_mutex); - - if(gssapi_krb5_context == NULL) { - ret = krb5_init_context (&gssapi_krb5_context); - } - if (ret == 0 && !created_key) { - HEIMDAL_key_create(&gssapi_context_key, - gssapi_destroy_thread_context, - ret); - if (ret) { - krb5_free_context(gssapi_krb5_context); - gssapi_krb5_context = NULL; - } else - created_key = 1; - } + HEIMDAL_MUTEX_unlock(&_gsskrb5_context_mutex); - HEIMDAL_MUTEX_unlock(&gssapi_krb5_context_mutex); -#endif return ret; } diff --git a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c new file mode 100644 index 0000000000..00f2543833 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c @@ -0,0 +1,789 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: init_sec_context.c,v 1.72 2006/10/24 23:03:19 lha Exp $"); + +/* + * copy the addresses from `input_chan_bindings' (if any) to + * the auth context `ac' + */ + +static OM_uint32 +set_addresses (krb5_auth_context ac, + const gss_channel_bindings_t input_chan_bindings) +{ + /* Port numbers are expected to be in application_data.value, + * initator's port first */ + + krb5_address initiator_addr, acceptor_addr; + krb5_error_code kret; + + if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS + || input_chan_bindings->application_data.length != + 2 * sizeof(ac->local_port)) + return 0; + + memset(&initiator_addr, 0, sizeof(initiator_addr)); + memset(&acceptor_addr, 0, sizeof(acceptor_addr)); + + ac->local_port = + *(int16_t *) input_chan_bindings->application_data.value; + + ac->remote_port = + *((int16_t *) input_chan_bindings->application_data.value + 1); + + kret = _gsskrb5i_address_to_krb5addr(input_chan_bindings->acceptor_addrtype, + &input_chan_bindings->acceptor_address, + ac->remote_port, + &acceptor_addr); + if (kret) + return kret; + + kret = _gsskrb5i_address_to_krb5addr(input_chan_bindings->initiator_addrtype, + &input_chan_bindings->initiator_address, + ac->local_port, + &initiator_addr); + if (kret) { + krb5_free_address (_gsskrb5_context, &acceptor_addr); + return kret; + } + + kret = krb5_auth_con_setaddrs(_gsskrb5_context, + ac, + &initiator_addr, /* local address */ + &acceptor_addr); /* remote address */ + + krb5_free_address (_gsskrb5_context, &initiator_addr); + krb5_free_address (_gsskrb5_context, &acceptor_addr); + +#if 0 + free(input_chan_bindings->application_data.value); + input_chan_bindings->application_data.value = NULL; + input_chan_bindings->application_data.length = 0; +#endif + + return kret; +} + +OM_uint32 +_gsskrb5_create_ctx( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_channel_bindings_t input_chan_bindings, + enum gss_ctx_id_t_state state) +{ + krb5_error_code kret; + gsskrb5_ctx ctx; + + *context_handle = NULL; + + ctx = malloc(sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + ctx->auth_context = NULL; + ctx->source = NULL; + ctx->target = NULL; + ctx->state = state; + ctx->flags = 0; + ctx->more_flags = 0; + ctx->service_keyblock = NULL; + ctx->ticket = NULL; + krb5_data_zero(&ctx->fwd_data); + ctx->lifetime = GSS_C_INDEFINITE; + ctx->order = NULL; + HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + + kret = krb5_auth_con_init (_gsskrb5_context, &ctx->auth_context); + if (kret) { + *minor_status = kret; + _gsskrb5_set_error_string (); + + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + + return GSS_S_FAILURE; + } + + kret = set_addresses(ctx->auth_context, input_chan_bindings); + if (kret) { + *minor_status = kret; + + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + + krb5_auth_con_free(_gsskrb5_context, ctx->auth_context); + + return GSS_S_BAD_BINDINGS; + } + + /* + * We need a sequence number + */ + + krb5_auth_con_addflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE | + KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED, + NULL); + + *context_handle = (gss_ctx_id_t)ctx; + + return GSS_S_COMPLETE; +} + + +static OM_uint32 +gsskrb5_get_creds( + OM_uint32 * minor_status, + krb5_ccache ccache, + gsskrb5_ctx ctx, + krb5_const_principal target_name, + OM_uint32 time_req, + OM_uint32 * time_rec, + krb5_creds ** cred) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_creds this_cred; + OM_uint32 lifetime_rec; + + *cred = NULL; + + memset(&this_cred, 0, sizeof(this_cred)); + this_cred.client = ctx->source; + this_cred.server = ctx->target; + + if (time_req && time_req != GSS_C_INDEFINITE) { + krb5_timestamp ts; + + krb5_timeofday (_gsskrb5_context, &ts); + this_cred.times.endtime = ts + time_req; + } else { + this_cred.times.endtime = 0; + } + + this_cred.session.keytype = KEYTYPE_NULL; + + kret = krb5_get_credentials(_gsskrb5_context, + 0, + ccache, + &this_cred, + cred); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + ctx->lifetime = (*cred)->times.endtime; + + ret = _gsskrb5_lifetime_left(minor_status, ctx->lifetime, &lifetime_rec); + if (ret) return ret; + + if (lifetime_rec == 0) { + *minor_status = 0; + return GSS_S_CONTEXT_EXPIRED; + } + + if (time_rec) *time_rec = lifetime_rec; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +gsskrb5_initiator_ready( + OM_uint32 * minor_status, + gsskrb5_ctx ctx) +{ + OM_uint32 ret; + int32_t seq_number; + int is_cfx = 0; + OM_uint32 flags = ctx->flags; + + krb5_auth_getremoteseqnumber (_gsskrb5_context, + ctx->auth_context, + &seq_number); + + _gsskrb5i_is_cfx(ctx, &is_cfx); + + ret = _gssapi_msg_order_create(minor_status, + &ctx->order, + _gssapi_msg_order_f(flags), + seq_number, 0, is_cfx); + if (ret) return ret; + + ctx->state = INITIATOR_READY; + ctx->more_flags |= OPEN; + + return GSS_S_COMPLETE; +} + +/* + * handle delegated creds in init-sec-context + */ + +static void +do_delegation (krb5_auth_context ac, + krb5_ccache ccache, + krb5_creds *cred, + krb5_const_principal name, + krb5_data *fwd_data, + uint32_t *flags) +{ + krb5_creds creds; + KDCOptions fwd_flags; + krb5_error_code kret; + + memset (&creds, 0, sizeof(creds)); + krb5_data_zero (fwd_data); + + kret = krb5_cc_get_principal(_gsskrb5_context, ccache, &creds.client); + if (kret) + goto out; + + kret = krb5_build_principal(_gsskrb5_context, + &creds.server, + strlen(creds.client->realm), + creds.client->realm, + KRB5_TGS_NAME, + creds.client->realm, + NULL); + if (kret) + goto out; + + creds.times.endtime = 0; + + memset(&fwd_flags, 0, sizeof(fwd_flags)); + fwd_flags.forwarded = 1; + fwd_flags.forwardable = 1; + + if ( /*target_name->name.name_type != KRB5_NT_SRV_HST ||*/ + name->name.name_string.len < 2) + goto out; + + kret = krb5_get_forwarded_creds(_gsskrb5_context, + ac, + ccache, + KDCOptions2int(fwd_flags), + name->name.name_string.val[1], + &creds, + fwd_data); + + out: + if (kret) + *flags &= ~GSS_C_DELEG_FLAG; + else + *flags |= GSS_C_DELEG_FLAG; + + if (creds.client) + krb5_free_principal(_gsskrb5_context, creds.client); + if (creds.server) + krb5_free_principal(_gsskrb5_context, creds.server); +} + +/* + * first stage of init-sec-context + */ + +static OM_uint32 +init_auth +(OM_uint32 * minor_status, + gsskrb5_cred initiator_cred_handle, + gsskrb5_ctx ctx, + krb5_const_principal name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret = GSS_S_FAILURE; + krb5_error_code kret; + krb5_flags ap_options; + krb5_creds *cred = NULL; + krb5_data outbuf; + krb5_ccache ccache = NULL; + uint32_t flags; + krb5_data authenticator; + Checksum cksum; + krb5_enctype enctype; + krb5_data fwd_data; + OM_uint32 lifetime_rec; + + krb5_data_zero(&outbuf); + krb5_data_zero(&fwd_data); + + *minor_status = 0; + + if (actual_mech_type) + *actual_mech_type = GSS_KRB5_MECHANISM; + + if (initiator_cred_handle == NULL) { + kret = krb5_cc_default (_gsskrb5_context, &ccache); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + } else + ccache = initiator_cred_handle->ccache; + + kret = krb5_cc_get_principal (_gsskrb5_context, ccache, &ctx->source); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_copy_principal (_gsskrb5_context, name, &ctx->target); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + ret = _gss_DES3_get_mic_compat(minor_status, ctx); + if (ret) + goto failure; + + + ret = gsskrb5_get_creds(minor_status, + ccache, + ctx, + ctx->target, + time_req, + time_rec, + &cred); + if (ret) + goto failure; + + ctx->lifetime = cred->times.endtime; + + ret = _gsskrb5_lifetime_left(minor_status, + ctx->lifetime, + &lifetime_rec); + if (ret) { + goto failure; + } + + if (lifetime_rec == 0) { + *minor_status = 0; + ret = GSS_S_CONTEXT_EXPIRED; + goto failure; + } + + krb5_auth_con_setkey(_gsskrb5_context, + ctx->auth_context, + &cred->session); + + kret = krb5_auth_con_generatelocalsubkey(_gsskrb5_context, + ctx->auth_context, + &cred->session); + if(kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + /* + * If the credential doesn't have ok-as-delegate, check what local + * policy say about ok-as-delegate, default is FALSE that makes + * code ignore the KDC setting and follow what the application + * requested. If its TRUE, strip of the GSS_C_DELEG_FLAG if the + * KDC doesn't set ok-as-delegate. + */ + if (!cred->flags.b.ok_as_delegate) { + krb5_boolean delegate; + + krb5_appdefault_boolean(_gsskrb5_context, + "gssapi", name->realm, + "ok-as-delegate", FALSE, &delegate); + if (delegate) + req_flags &= ~GSS_C_DELEG_FLAG; + } + + flags = 0; + ap_options = 0; + if (req_flags & GSS_C_DELEG_FLAG) + do_delegation (ctx->auth_context, + ccache, cred, name, &fwd_data, &flags); + + if (req_flags & GSS_C_MUTUAL_FLAG) { + flags |= GSS_C_MUTUAL_FLAG; + ap_options |= AP_OPTS_MUTUAL_REQUIRED; + } + + if (req_flags & GSS_C_REPLAY_FLAG) + flags |= GSS_C_REPLAY_FLAG; + if (req_flags & GSS_C_SEQUENCE_FLAG) + flags |= GSS_C_SEQUENCE_FLAG; + if (req_flags & GSS_C_ANON_FLAG) + ; /* XXX */ + if (req_flags & GSS_C_DCE_STYLE) { + /* GSS_C_DCE_STYLE implies GSS_C_MUTUAL_FLAG */ + flags |= GSS_C_DCE_STYLE | GSS_C_MUTUAL_FLAG; + ap_options |= AP_OPTS_MUTUAL_REQUIRED; + } + if (req_flags & GSS_C_IDENTIFY_FLAG) + flags |= GSS_C_IDENTIFY_FLAG; + if (req_flags & GSS_C_EXTENDED_ERROR_FLAG) + flags |= GSS_C_EXTENDED_ERROR_FLAG; + + flags |= GSS_C_CONF_FLAG; + flags |= GSS_C_INTEG_FLAG; + flags |= GSS_C_TRANS_FLAG; + + if (ret_flags) + *ret_flags = flags; + ctx->flags = flags; + ctx->more_flags |= LOCAL; + + ret = _gsskrb5_create_8003_checksum (minor_status, + input_chan_bindings, + flags, + &fwd_data, + &cksum); + krb5_data_free (&fwd_data); + if (ret) + goto failure; + + enctype = ctx->auth_context->keyblock->keytype; + + kret = krb5_build_authenticator (_gsskrb5_context, + ctx->auth_context, + enctype, + cred, + &cksum, + NULL, + &authenticator, + KRB5_KU_AP_REQ_AUTH); + + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_build_ap_req (_gsskrb5_context, + enctype, + cred, + ap_options, + authenticator, + &outbuf); + + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + ret = GSS_S_FAILURE; + goto failure; + } + + ret = _gsskrb5_encapsulate (minor_status, &outbuf, output_token, + (u_char *)"\x01\x00", GSS_KRB5_MECHANISM); + if (ret) + goto failure; + + krb5_data_free (&outbuf); + krb5_free_creds(_gsskrb5_context, cred); + free_Checksum(&cksum); + if (initiator_cred_handle == NULL) + krb5_cc_close(_gsskrb5_context, ccache); + + if (flags & GSS_C_MUTUAL_FLAG) { + ctx->state = INITIATOR_WAIT_FOR_MUTAL; + return GSS_S_CONTINUE_NEEDED; + } + + return gsskrb5_initiator_ready(minor_status, ctx); +failure: + if(cred) + krb5_free_creds(_gsskrb5_context, cred); + if (ccache && initiator_cred_handle == NULL) + krb5_cc_close(_gsskrb5_context, ccache); + + return ret; + +} + +static OM_uint32 +repl_mutual + (OM_uint32 * minor_status, + gsskrb5_ctx ctx, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_data indata; + krb5_ap_rep_enc_part *repl; + int is_cfx = 0; + + output_token->length = 0; + output_token->value = NULL; + + if (actual_mech_type) + *actual_mech_type = GSS_KRB5_MECHANISM; + + if (req_flags & GSS_C_DCE_STYLE) { + /* There is no OID wrapping. */ + indata.length = input_token->length; + indata.data = input_token->value; + } else { + ret = _gsskrb5_decapsulate (minor_status, + input_token, + &indata, + "\x02\x00", + GSS_KRB5_MECHANISM); + if (ret) { + /* XXX - Handle AP_ERROR */ + return ret; + } + } + + kret = krb5_rd_rep (_gsskrb5_context, + ctx->auth_context, + &indata, + &repl); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + krb5_free_ap_rep_enc_part (_gsskrb5_context, + repl); + + _gsskrb5i_is_cfx(ctx, &is_cfx); + if (is_cfx) { + krb5_keyblock *key = NULL; + + kret = krb5_auth_con_getremotesubkey(_gsskrb5_context, + ctx->auth_context, + &key); + if (kret == 0 && key != NULL) { + ctx->more_flags |= ACCEPTOR_SUBKEY; + krb5_free_keyblock (_gsskrb5_context, key); + } + } + + + *minor_status = 0; + if (time_rec) { + ret = _gsskrb5_lifetime_left(minor_status, + ctx->lifetime, + time_rec); + } else { + ret = GSS_S_COMPLETE; + } + if (ret_flags) + *ret_flags = ctx->flags; + + if (req_flags & GSS_C_DCE_STYLE) { + int32_t con_flags; + krb5_data outbuf; + + /* Do don't do sequence number for the mk-rep */ + krb5_auth_con_removeflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE, + &con_flags); + + kret = krb5_mk_rep(_gsskrb5_context, + ctx->auth_context, + &outbuf); + if (kret) { + _gsskrb5_set_error_string (); + *minor_status = kret; + return GSS_S_FAILURE; + } + + output_token->length = outbuf.length; + output_token->value = outbuf.data; + + krb5_auth_con_removeflags(_gsskrb5_context, + ctx->auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE, + NULL); + } + + return gsskrb5_initiator_ready(minor_status, ctx); +} + +/* + * gss_init_sec_context + */ + +OM_uint32 _gsskrb5_init_sec_context +(OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + gsskrb5_cred cred = (gsskrb5_cred)initiator_cred_handle; + krb5_const_principal name = (krb5_const_principal)target_name; + gsskrb5_ctx ctx; + OM_uint32 ret; + + GSSAPI_KRB5_INIT (); + + output_token->length = 0; + output_token->value = NULL; + + if (context_handle == NULL) { + *minor_status = 0; + return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; + } + + if (ret_flags) + *ret_flags = 0; + if (time_rec) + *time_rec = 0; + + if (target_name == GSS_C_NO_NAME) { + if (actual_mech_type) + *actual_mech_type = GSS_C_NO_OID; + *minor_status = 0; + return GSS_S_BAD_NAME; + } + + if (mech_type != GSS_C_NO_OID && + !gss_oid_equal(mech_type, GSS_KRB5_MECHANISM)) + return GSS_S_BAD_MECH; + + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) { + OM_uint32 ret; + + if (*context_handle != GSS_C_NO_CONTEXT) { + *minor_status = 0; + return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; + } + + ret = _gsskrb5_create_ctx(minor_status, + context_handle, + input_chan_bindings, + INITIATOR_START); + if (ret) + return ret; + } + + if (*context_handle == GSS_C_NO_CONTEXT) { + *minor_status = 0; + return GSS_S_FAILURE | GSS_S_CALL_BAD_STRUCTURE; + } + + ctx = (gsskrb5_ctx) *context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + switch (ctx->state) { + case INITIATOR_START: + ret = init_auth(minor_status, + cred, + ctx, + name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + break; + case INITIATOR_WAIT_FOR_MUTAL: + ret = repl_mutual(minor_status, + ctx, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + break; + case INITIATOR_READY: + /* + * If we get there, the caller have called + * gss_init_sec_context() one time too many. + */ + *minor_status = 0; + ret = GSS_S_BAD_STATUS; + break; + default: + *minor_status = 0; + ret = GSS_S_BAD_STATUS; + break; + } + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + /* destroy context in case of error */ + if (GSS_ERROR(ret)) { + OM_uint32 min2; + _gsskrb5_delete_sec_context(&min2, context_handle, GSS_C_NO_BUFFER); + } + + return ret; + +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_context.c b/source4/heimdal/lib/gssapi/krb5/inquire_context.c new file mode 100644 index 0000000000..ef43e6852c --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_context.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1997, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_context.c,v 1.10 2006/10/07 22:15:03 lha Exp $"); + +OM_uint32 _gsskrb5_inquire_context ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open_context + ) +{ + OM_uint32 ret; + gsskrb5_ctx ctx = (gsskrb5_ctx)context_handle; + gss_name_t name; + + if (src_name) + *src_name = GSS_C_NO_NAME; + if (targ_name) + *targ_name = GSS_C_NO_NAME; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (src_name) { + name = (gss_name_t)ctx->source; + ret = _gsskrb5_duplicate_name (minor_status, name, src_name); + if (ret) + goto failed; + } + + if (targ_name) { + name = (gss_name_t)ctx->target; + ret = _gsskrb5_duplicate_name (minor_status, name, targ_name); + if (ret) + goto failed; + } + + if (lifetime_rec) { + ret = _gsskrb5_lifetime_left(minor_status, + ctx->lifetime, + lifetime_rec); + if (ret) + goto failed; + } + + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (ctx_flags) + *ctx_flags = ctx->flags; + + if (locally_initiated) + *locally_initiated = ctx->more_flags & LOCAL; + + if (open_context) + *open_context = ctx->more_flags & OPEN; + + *minor_status = 0; + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_COMPLETE; + +failed: + if (src_name) + _gsskrb5_release_name(NULL, src_name); + if (targ_name) + _gsskrb5_release_name(NULL, targ_name); + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred.c new file mode 100644 index 0000000000..0593729365 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 1997, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_cred.c,v 1.12 2006/10/07 22:15:06 lha Exp $"); + +OM_uint32 _gsskrb5_inquire_cred +(OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + gss_name_t * output_name, + OM_uint32 * lifetime, + gss_cred_usage_t * cred_usage, + gss_OID_set * mechanisms + ) +{ + gss_cred_id_t aqcred_init = GSS_C_NO_CREDENTIAL; + gss_cred_id_t aqcred_accept = GSS_C_NO_CREDENTIAL; + gsskrb5_cred acred = NULL, icred = NULL; + OM_uint32 ret; + + *minor_status = 0; + + if (output_name) + *output_name = NULL; + if (mechanisms) + *mechanisms = GSS_C_NO_OID_SET; + + if (cred_handle == GSS_C_NO_CREDENTIAL) { + ret = _gsskrb5_acquire_cred(minor_status, + GSS_C_NO_NAME, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + GSS_C_ACCEPT, + &aqcred_accept, + NULL, + NULL); + if (ret == GSS_S_COMPLETE) + acred = (gsskrb5_cred)aqcred_accept; + + ret = _gsskrb5_acquire_cred(minor_status, + GSS_C_NO_NAME, + GSS_C_INDEFINITE, + GSS_C_NO_OID_SET, + GSS_C_INITIATE, + &aqcred_init, + NULL, + NULL); + if (ret == GSS_S_COMPLETE) + acred = (gsskrb5_cred)aqcred_init; + + if (icred == NULL && acred == NULL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + } else + acred = (gsskrb5_cred)cred_handle; + + if (acred) + HEIMDAL_MUTEX_lock(&acred->cred_id_mutex); + if (icred) + HEIMDAL_MUTEX_lock(&icred->cred_id_mutex); + + if (output_name != NULL) { + if (icred && icred->principal != NULL) { + gss_name_t name; + + if (acred) + name = (gss_name_t)acred->principal; + else + name = (gss_name_t)icred->principal; + + ret = _gsskrb5_duplicate_name(minor_status, name, output_name); + if (ret) + goto out; + } else if (acred && acred->usage == GSS_C_ACCEPT) { + krb5_principal princ; + *minor_status = krb5_sname_to_principal(_gsskrb5_context, NULL, + NULL, KRB5_NT_SRV_HST, + &princ); + if (*minor_status) { + ret = GSS_S_FAILURE; + goto out; + } + *output_name = (gss_name_t)princ; + } else { + krb5_principal princ; + *minor_status = krb5_get_default_principal(_gsskrb5_context, + &princ); + if (*minor_status) { + ret = GSS_S_FAILURE; + goto out; + } + *output_name = (gss_name_t)princ; + } + } + if (lifetime != NULL) { + OM_uint32 alife = GSS_C_INDEFINITE, ilife = GSS_C_INDEFINITE; + + if (acred) alife = acred->lifetime; + if (icred) ilife = icred->lifetime; + + ret = _gsskrb5_lifetime_left(minor_status, + min(alife,ilife), + lifetime); + if (ret) + goto out; + } + if (cred_usage != NULL) { + if (acred && icred) + *cred_usage = GSS_C_BOTH; + else if (acred) + *cred_usage = GSS_C_ACCEPT; + else if (icred) + *cred_usage = GSS_C_INITIATE; + else + abort(); + } + + if (mechanisms != NULL) { + ret = _gsskrb5_create_empty_oid_set(minor_status, mechanisms); + if (ret) + goto out; + if (acred) + ret = _gsskrb5_add_oid_set_member(minor_status, + &acred->mechanisms->elements[0], + mechanisms); + if (ret == GSS_S_COMPLETE && icred) + ret = _gsskrb5_add_oid_set_member(minor_status, + &icred->mechanisms->elements[0], + mechanisms); + if (ret) + goto out; + } + ret = GSS_S_COMPLETE; +out: + if (acred) + HEIMDAL_MUTEX_unlock(&acred->cred_id_mutex); + if (icred) + HEIMDAL_MUTEX_unlock(&icred->cred_id_mutex); + + if (aqcred_init != GSS_C_NO_CREDENTIAL) + ret = _gsskrb5_release_cred(minor_status, &aqcred_init); + if (aqcred_accept != GSS_C_NO_CREDENTIAL) + ret = _gsskrb5_release_cred(minor_status, &aqcred_accept); + + return ret; +} diff --git a/source4/heimdal/lib/gssapi/arcfour.h b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c index 0406b64b09..954a5e3119 100644 --- a/source4/heimdal/lib/gssapi/arcfour.h +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c @@ -31,53 +31,53 @@ * SUCH DAMAGE. */ -/* $Id: arcfour.h,v 1.5 2004/03/07 22:30:57 lha Exp $ */ +#include "krb5/gsskrb5_locl.h" -#ifndef GSSAPI_ARCFOUR_H_ -#define GSSAPI_ARCFOUR_H_ 1 +RCSID("$Id: inquire_cred_by_mech.c,v 1.4 2006/10/07 22:15:08 lha Exp $"); -#define GSS_ARCFOUR_WRAP_TOKEN_SIZE 32 -#define GSS_ARCFOUR_WRAP_TOKEN_OFFSET 13 +OM_uint32 _gsskrb5_inquire_cred_by_mech ( + OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t * name, + OM_uint32 * initiator_lifetime, + OM_uint32 * acceptor_lifetime, + gss_cred_usage_t * cred_usage + ) +{ + OM_uint32 ret; + OM_uint32 lifetime; -OM_uint32 _gssapi_wrap_arcfour(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, - int conf_req_flag, - gss_qop_t qop_req, - const gss_buffer_t input_message_buffer, - int *conf_state, - gss_buffer_t output_message_buffer, - krb5_keyblock *key); + if (gss_oid_equal(mech_type, GSS_C_NO_OID) == 0 && + gss_oid_equal(mech_type, GSS_KRB5_MECHANISM) == 0) { + *minor_status = EINVAL; + return GSS_S_BAD_MECH; + } -OM_uint32 _gssapi_unwrap_arcfour(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, - const gss_buffer_t input_message_buffer, - gss_buffer_t output_message_buffer, - int *conf_state, - gss_qop_t *qop_state, - krb5_keyblock *key); + ret = _gsskrb5_inquire_cred (minor_status, + cred_handle, + name, + &lifetime, + cred_usage, + NULL); + + if (ret == 0 && cred_handle != GSS_C_NO_CREDENTIAL) { + gsskrb5_cred cred = (gsskrb5_cred)cred_handle; + gss_cred_usage_t usage; -OM_uint32 _gssapi_get_mic_arcfour(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, - gss_qop_t qop_req, - const gss_buffer_t message_buffer, - gss_buffer_t message_token, - krb5_keyblock *key); + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + usage = cred->usage; + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); -OM_uint32 _gssapi_verify_mic_arcfour(OM_uint32 *minor_status, - const gss_ctx_id_t context_handle, - const gss_buffer_t message_buffer, - const gss_buffer_t token_buffer, - gss_qop_t *qop_state, - krb5_keyblock *key, - char *type); -OM_uint32 -_gssapi_wrap_size_arcfour(OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, - int conf_req_flag, - gss_qop_t qop_req, - OM_uint32 req_input_size, - OM_uint32 * output_size, - OM_uint32 * padlen, - krb5_keyblock *key); + if (initiator_lifetime) { + if (usage == GSS_C_INITIATE || usage == GSS_C_BOTH) + *initiator_lifetime = lifetime; + } + if (acceptor_lifetime) { + if (usage == GSS_C_ACCEPT || usage == GSS_C_BOTH) + *acceptor_lifetime = lifetime; + } + } -#endif /* GSSAPI_ARCFOUR_H_ */ + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c new file mode 100644 index 0000000000..26927c740c --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_cred_by_oid.c,v 1.4 2006/10/07 22:15:10 lha Exp $"); + +OM_uint32 _gsskrb5_inquire_cred_by_oid + (OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + gsskrb5_cred cred = (gsskrb5_cred)cred_handle; + krb5_error_code ret; + gss_buffer_desc buffer; + char *str; + + if (gss_oid_equal(desired_object, GSS_KRB5_COPY_CCACHE_X) == 0) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); + + if (cred->ccache == NULL) { + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ret = krb5_cc_get_full_name(_gsskrb5_context, cred->ccache, &str); + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + if (ret) { + *minor_status = ret; + _gsskrb5_set_error_string (); + return GSS_S_FAILURE; + } + + buffer.value = str; + buffer.length = strlen(str); + + ret = gss_add_buffer_set_member(minor_status, &buffer, data_set); + if (ret != GSS_S_COMPLETE) + _gsskrb5_clear_status (); + + free(str); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c b/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c new file mode 100644 index 0000000000..5c1f082f45 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_mechs_for_name.c,v 1.3 2006/10/07 22:15:13 lha Exp $"); + +OM_uint32 _gsskrb5_inquire_mechs_for_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + gss_OID_set * mech_types + ) +{ + OM_uint32 ret; + + ret = _gsskrb5_create_empty_oid_set(minor_status, mech_types); + if (ret) + return ret; + + ret = _gsskrb5_add_oid_set_member(minor_status, + GSS_KRB5_MECHANISM, + mech_types); + if (ret) + _gsskrb5_release_oid_set(NULL, mech_types); + + return ret; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c b/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c new file mode 100644 index 0000000000..5d8aefab1c --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_names_for_mech.c,v 1.3 2006/10/07 22:15:15 lha Exp $"); + + +static gss_OID *name_list[] = { + &GSS_C_NT_HOSTBASED_SERVICE, + &GSS_C_NT_USER_NAME, + &GSS_KRB5_NT_PRINCIPAL_NAME, + &GSS_C_NT_EXPORT_NAME, + NULL +}; + +OM_uint32 _gsskrb5_inquire_names_for_mech ( + OM_uint32 * minor_status, + const gss_OID mechanism, + gss_OID_set * name_types + ) +{ + OM_uint32 ret; + int i; + + *minor_status = 0; + + if (gss_oid_equal(mechanism, GSS_KRB5_MECHANISM) == 0 && + gss_oid_equal(mechanism, GSS_C_NULL_OID) == 0) { + *name_types = GSS_C_NO_OID_SET; + return GSS_S_BAD_MECH; + } + + ret = _gsskrb5_create_empty_oid_set(minor_status, name_types); + if (ret != GSS_S_COMPLETE) + return ret; + + for (i = 0; name_list[i] != NULL; i++) { + ret = _gsskrb5_add_oid_set_member(minor_status, + *(name_list[i]), + name_types); + if (ret != GSS_S_COMPLETE) + break; + } + + if (ret != GSS_S_COMPLETE) + _gsskrb5_release_oid_set(NULL, name_types); + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c b/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c new file mode 100644 index 0000000000..0b46cc5495 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c @@ -0,0 +1,559 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: inquire_sec_context_by_oid.c,v 1.8 2006/10/24 15:55:28 lha Exp $"); + +static int +oid_prefix_equal(gss_OID oid_enc, gss_OID prefix_enc, unsigned *suffix) +{ + int ret; + heim_oid oid; + heim_oid prefix; + + *suffix = 0; + + ret = der_get_oid(oid_enc->elements, oid_enc->length, + &oid, NULL); + if (ret) { + return 0; + } + + ret = der_get_oid(prefix_enc->elements, prefix_enc->length, + &prefix, NULL); + if (ret) { + der_free_oid(&oid); + return 0; + } + + ret = 0; + + if (oid.length - 1 == prefix.length) { + *suffix = oid.components[oid.length - 1]; + oid.length--; + ret = (der_heim_oid_cmp(&oid, &prefix) == 0); + oid.length++; + } + + der_free_oid(&oid); + der_free_oid(&prefix); + + return ret; +} + +static OM_uint32 inquire_sec_context_tkt_flags + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + gss_buffer_set_t *data_set) +{ + OM_uint32 tkt_flags; + unsigned char buf[4]; + gss_buffer_desc value; + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + if (context_handle->ticket == NULL) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + _gsskrb5_set_status("No ticket from which to obtain flags"); + *minor_status = EINVAL; + return GSS_S_BAD_MECH; + } + + tkt_flags = TicketFlags2int(context_handle->ticket->ticket.flags); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + _gsskrb5_encode_om_uint32(tkt_flags, buf); + value.length = sizeof(buf); + value.value = buf; + + return gss_add_buffer_set_member(minor_status, + &value, + data_set); +} + +enum keytype { ACCEPTOR_KEY, INITIATOR_KEY, TOKEN_KEY }; + +static OM_uint32 inquire_sec_context_get_subkey + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + enum keytype keytype, + gss_buffer_set_t *data_set) +{ + krb5_keyblock *key = NULL; + krb5_storage *sp = NULL; + krb5_data data; + OM_uint32 maj_stat = GSS_S_COMPLETE; + krb5_error_code ret; + + krb5_data_zero(&data); + + sp = krb5_storage_emem(); + if (sp == NULL) { + _gsskrb5_clear_status(); + ret = ENOMEM; + goto out; + } + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + switch(keytype) { + case ACCEPTOR_KEY: + ret = _gsskrb5i_get_acceptor_subkey(context_handle, &key); + if (ret) + _gsskrb5_set_error_string (); + break; + case INITIATOR_KEY: + ret = _gsskrb5i_get_initiator_subkey(context_handle, &key); + if (ret) + _gsskrb5_set_error_string (); + break; + case TOKEN_KEY: + ret = _gsskrb5i_get_token_key(context_handle, &key); + if (ret) + _gsskrb5_set_error_string (); + break; + default: + _gsskrb5_set_status("%d is not a valid subkey type", keytype); + ret = EINVAL; + break; + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (ret) + goto out; + + ret = krb5_store_keyblock(sp, *key); + krb5_free_keyblock (_gsskrb5_context, key); + if (ret) { + _gsskrb5_set_error_string (); + goto out; + } + + ret = krb5_storage_to_data(sp, &data); + if (ret) { + _gsskrb5_set_error_string (); + goto out; + } + + { + gss_buffer_desc value; + + value.length = data.length; + value.value = data.data; + + maj_stat = gss_add_buffer_set_member(minor_status, + &value, + data_set); + } + +out: + krb5_data_free(&data); + if (sp) + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + maj_stat = GSS_S_FAILURE; + } + return maj_stat; +} + +static OM_uint32 inquire_sec_context_authz_data + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + unsigned ad_type, + gss_buffer_set_t *data_set) +{ + krb5_data data; + gss_buffer_desc ad_data; + OM_uint32 ret; + + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + if (context_handle->ticket == NULL) { + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + *minor_status = EINVAL; + _gsskrb5_set_status("No ticket to obtain authz data from"); + return GSS_S_NO_CONTEXT; + } + + ret = krb5_ticket_get_authorization_data_type(_gsskrb5_context, + context_handle->ticket, + ad_type, + &data); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + return GSS_S_FAILURE; + } + + ad_data.value = data.data; + ad_data.length = data.length; + + ret = gss_add_buffer_set_member(minor_status, + &ad_data, + data_set); + + krb5_data_free(&data); + + return ret; +} + +static OM_uint32 inquire_sec_context_has_updated_spnego + (OM_uint32 *minor_status, + const gsskrb5_ctx context_handle, + gss_buffer_set_t *data_set) +{ + int is_updated = 0; + + *minor_status = 0; + *data_set = GSS_C_NO_BUFFER_SET; + + /* + * For Windows SPNEGO implementations, both the initiator and the + * acceptor are assumed to have been updated if a "newer" [CLAR] or + * different enctype is negotiated for use by the Kerberos GSS-API + * mechanism. + */ + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + _gsskrb5i_is_cfx(context_handle, &is_updated); + if (is_updated == 0) { + krb5_keyblock *acceptor_subkey; + + if (context_handle->more_flags & LOCAL) + acceptor_subkey = context_handle->auth_context->remote_subkey; + else + acceptor_subkey = context_handle->auth_context->local_subkey; + + if (acceptor_subkey != NULL) + is_updated = (acceptor_subkey->keytype != + context_handle->auth_context->keyblock->keytype); + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + + return is_updated ? GSS_S_COMPLETE : GSS_S_FAILURE; +} + +/* + * + */ + +static OM_uint32 +export_lucid_sec_context_v1(OM_uint32 *minor_status, + gsskrb5_ctx context_handle, + gss_buffer_set_t *data_set) +{ + krb5_storage *sp = NULL; + OM_uint32 major_status = GSS_S_COMPLETE; + krb5_error_code ret; + krb5_keyblock *key = NULL; + int32_t number; + int is_cfx; + krb5_data data; + + *minor_status = 0; + + GSSAPI_KRB5_INIT (); + + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + + _gsskrb5i_is_cfx(context_handle, &is_cfx); + + sp = krb5_storage_emem(); + if (sp == NULL) { + _gsskrb5_clear_status(); + ret = ENOMEM; + goto out; + } + + ret = krb5_store_int32(sp, 1); + if (ret) goto out; + ret = krb5_store_int32(sp, (context_handle->more_flags & LOCAL) ? 1 : 0); + if (ret) goto out; + ret = krb5_store_int32(sp, context_handle->lifetime); + if (ret) goto out; + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, + context_handle->auth_context, + &number); + ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */ + ret = krb5_store_uint32(sp, (uint32_t)number); + krb5_auth_getremoteseqnumber (_gsskrb5_context, + context_handle->auth_context, + &number); + ret = krb5_store_uint32(sp, (uint32_t)0); /* store top half as zero */ + ret = krb5_store_uint32(sp, (uint32_t)number); + ret = krb5_store_int32(sp, (is_cfx) ? 1 : 0); + if (ret) goto out; + + ret = _gsskrb5i_get_token_key(context_handle, &key); + if (ret) goto out; + + if (is_cfx == 0) { + int sign_alg, seal_alg; + + switch (key->keytype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + sign_alg = 0; + seal_alg = 0; + break; + case ETYPE_DES3_CBC_MD5: + case ETYPE_DES3_CBC_SHA1: + sign_alg = 4; + seal_alg = 2; + break; + case ETYPE_ARCFOUR_HMAC_MD5: + case ETYPE_ARCFOUR_HMAC_MD5_56: + sign_alg = 17; + seal_alg = 16; + break; + default: + sign_alg = -1; + seal_alg = -1; + break; + } + ret = krb5_store_int32(sp, sign_alg); + if (ret) goto out; + ret = krb5_store_int32(sp, seal_alg); + if (ret) goto out; + /* ctx_key */ + ret = krb5_store_keyblock(sp, *key); + if (ret) goto out; + } else { + int subkey_p = (context_handle->more_flags & ACCEPTOR_SUBKEY) ? 1 : 0; + + /* have_acceptor_subkey */ + ret = krb5_store_int32(sp, subkey_p); + if (ret) goto out; + /* ctx_key */ + ret = krb5_store_keyblock(sp, *key); + if (ret) goto out; + /* acceptor_subkey */ + if (subkey_p) { + ret = krb5_store_keyblock(sp, *key); + if (ret) goto out; + } + } + ret = krb5_storage_to_data(sp, &data); + if (ret) goto out; + + { + gss_buffer_desc ad_data; + + ad_data.value = data.data; + ad_data.length = data.length; + + ret = gss_add_buffer_set_member(minor_status, &ad_data, data_set); + krb5_data_free(&data); + if (ret) + goto out; + } + +out: + if (key) + krb5_free_keyblock (_gsskrb5_context, key); + if (sp) + krb5_storage_free(sp); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + } + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + return major_status; +} + +static OM_uint32 +get_authtime(OM_uint32 *minor_status, + gsskrb5_ctx ctx, + gss_buffer_set_t *data_set) + +{ + gss_buffer_desc value; + OM_uint32 authtime; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + if (ctx->ticket == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + _gsskrb5_set_status("No ticket to obtain auth time from"); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + authtime = ctx->ticket->ticket.authtime; + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + value.length = 4; + value.value = malloc(value.length); + if (!value.value) { + _gsskrb5_clear_status(); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + _gsskrb5_encode_om_uint32(authtime, value.value); + + return gss_add_buffer_set_member(minor_status, + &value, + data_set); +} + + +static OM_uint32 +get_service_keyblock + (OM_uint32 *minor_status, + gsskrb5_ctx ctx, + gss_buffer_set_t *data_set) +{ + krb5_storage *sp = NULL; + krb5_data data; + OM_uint32 maj_stat = GSS_S_COMPLETE; + krb5_error_code ret = EINVAL; + + sp = krb5_storage_emem(); + if (sp == NULL) { + _gsskrb5_clear_status(); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + if (ctx->service_keyblock == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + _gsskrb5_set_status("No service keyblock on gssapi context"); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + krb5_data_zero(&data); + + ret = krb5_store_keyblock(sp, *ctx->service_keyblock); + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + if (ret) + goto out; + + ret = krb5_storage_to_data(sp, &data); + if (ret) + goto out; + + { + gss_buffer_desc value; + + value.length = data.length; + value.value = data.data; + + maj_stat = gss_add_buffer_set_member(minor_status, + &value, + data_set); + } + +out: + krb5_data_free(&data); + if (sp) + krb5_storage_free(sp); + if (ret) { + _gsskrb5_set_error_string (); + *minor_status = ret; + maj_stat = GSS_S_FAILURE; + } + return maj_stat; +} +/* + * + */ + +OM_uint32 _gsskrb5_inquire_sec_context_by_oid + (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; + unsigned suffix; + + if (ctx == NULL) { + *minor_status = EINVAL; + return GSS_S_NO_CONTEXT; + } + + if (gss_oid_equal(desired_object, GSS_KRB5_GET_TKT_FLAGS_X)) { + return inquire_sec_context_tkt_flags(minor_status, + ctx, + data_set); + } else if (gss_oid_equal(desired_object, GSS_C_PEER_HAS_UPDATED_SPNEGO)) { + return inquire_sec_context_has_updated_spnego(minor_status, + ctx, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + TOKEN_KEY, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_INITIATOR_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + INITIATOR_KEY, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_ACCEPTOR_SUBKEY_X)) { + return inquire_sec_context_get_subkey(minor_status, + ctx, + ACCEPTOR_KEY, + data_set); + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_AUTHTIME_X)) { + return get_authtime(minor_status, ctx, data_set); + } else if (oid_prefix_equal(desired_object, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X, + &suffix)) { + return inquire_sec_context_authz_data(minor_status, + ctx, + suffix, + data_set); + } else if (oid_prefix_equal(desired_object, + GSS_KRB5_EXPORT_LUCID_CONTEXT_X, + &suffix)) { + if (suffix == 1) + return export_lucid_sec_context_v1(minor_status, + ctx, + data_set); + *minor_status = 0; + return GSS_S_FAILURE; + } else if (gss_oid_equal(desired_object, GSS_KRB5_GET_SERVICE_KEYBLOCK_X)) { + return get_service_keyblock(minor_status, ctx, data_set); + } else { + *minor_status = 0; + return GSS_S_FAILURE; + } +} + diff --git a/source4/heimdal/lib/gssapi/krb5/process_context_token.c b/source4/heimdal/lib/gssapi/krb5/process_context_token.c new file mode 100644 index 0000000000..99568c9dd0 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/process_context_token.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: process_context_token.c,v 1.4 2006/10/07 22:15:19 lha Exp $"); + +OM_uint32 _gsskrb5_process_context_token ( + OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer + ) +{ + OM_uint32 ret = GSS_S_FAILURE; + gss_buffer_desc empty_buffer; + gss_qop_t qop_state; + + empty_buffer.length = 0; + empty_buffer.value = NULL; + + qop_state = GSS_C_QOP_DEFAULT; + + ret = _gsskrb5_verify_mic_internal(minor_status, + (gsskrb5_ctx)context_handle, + token_buffer, &empty_buffer, + GSS_C_QOP_DEFAULT, "\x01\x02"); + + if (ret == GSS_S_COMPLETE) + ret = _gsskrb5_delete_sec_context(minor_status, + rk_UNCONST(&context_handle), + GSS_C_NO_BUFFER); + if (ret == GSS_S_COMPLETE) + *minor_status = 0; + + return ret; +} diff --git a/source4/heimdal/lib/gssapi/release_buffer.c b/source4/heimdal/lib/gssapi/krb5/release_buffer.c index 258b76f627..b62ad02117 100644 --- a/source4/heimdal/lib/gssapi/release_buffer.c +++ b/source4/heimdal/lib/gssapi/krb5/release_buffer.c @@ -31,11 +31,11 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: release_buffer.c,v 1.5 2003/03/16 17:58:20 lha Exp $"); +RCSID("$Id: release_buffer.c,v 1.7 2006/10/07 22:15:22 lha Exp $"); -OM_uint32 gss_release_buffer +OM_uint32 _gsskrb5_release_buffer (OM_uint32 * minor_status, gss_buffer_t buffer ) diff --git a/source4/heimdal/lib/gssapi/release_cred.c b/source4/heimdal/lib/gssapi/krb5/release_cred.c index fc9fc3fc01..662461ccfd 100644 --- a/source4/heimdal/lib/gssapi/release_cred.c +++ b/source4/heimdal/lib/gssapi/krb5/release_cred.c @@ -31,43 +31,46 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: release_cred.c,v 1.11 2005/11/02 08:57:35 lha Exp $"); +RCSID("$Id: release_cred.c,v 1.13 2006/10/07 22:15:24 lha Exp $"); -OM_uint32 gss_release_cred +OM_uint32 _gsskrb5_release_cred (OM_uint32 * minor_status, gss_cred_id_t * cred_handle ) { + gsskrb5_cred cred; + *minor_status = 0; - if (*cred_handle == GSS_C_NO_CREDENTIAL) { + if (*cred_handle == NULL) return GSS_S_COMPLETE; - } + + cred = (gsskrb5_cred)*cred_handle; + *cred_handle = GSS_C_NO_CREDENTIAL; GSSAPI_KRB5_INIT (); - HEIMDAL_MUTEX_lock(&(*cred_handle)->cred_id_mutex); + HEIMDAL_MUTEX_lock(&cred->cred_id_mutex); - if ((*cred_handle)->principal != NULL) - krb5_free_principal(gssapi_krb5_context, (*cred_handle)->principal); - if ((*cred_handle)->keytab != NULL) - krb5_kt_close(gssapi_krb5_context, (*cred_handle)->keytab); - if ((*cred_handle)->ccache != NULL) { + if (cred->principal != NULL) + krb5_free_principal(_gsskrb5_context, cred->principal); + if (cred->keytab != NULL) + krb5_kt_close(_gsskrb5_context, cred->keytab); + if (cred->ccache != NULL) { const krb5_cc_ops *ops; - ops = krb5_cc_get_ops(gssapi_krb5_context, (*cred_handle)->ccache); - if ((*cred_handle)->cred_flags & GSS_CF_DESTROY_CRED_ON_RELEASE) - krb5_cc_destroy(gssapi_krb5_context, (*cred_handle)->ccache); + ops = krb5_cc_get_ops(_gsskrb5_context, cred->ccache); + if (cred->cred_flags & GSS_CF_DESTROY_CRED_ON_RELEASE) + krb5_cc_destroy(_gsskrb5_context, cred->ccache); else - krb5_cc_close(gssapi_krb5_context, (*cred_handle)->ccache); + krb5_cc_close(_gsskrb5_context, cred->ccache); } - gss_release_oid_set(NULL, &(*cred_handle)->mechanisms); - HEIMDAL_MUTEX_unlock(&(*cred_handle)->cred_id_mutex); - HEIMDAL_MUTEX_destroy(&(*cred_handle)->cred_id_mutex); - memset(*cred_handle, 0, sizeof(**cred_handle)); - free(*cred_handle); - *cred_handle = GSS_C_NO_CREDENTIAL; + _gsskrb5_release_oid_set(NULL, &cred->mechanisms); + HEIMDAL_MUTEX_unlock(&cred->cred_id_mutex); + HEIMDAL_MUTEX_destroy(&cred->cred_id_mutex); + memset(cred, 0, sizeof(*cred)); + free(cred); return GSS_S_COMPLETE; } diff --git a/source4/heimdal/lib/gssapi/release_name.c b/source4/heimdal/lib/gssapi/krb5/release_name.c index 6894ffae49..a92ad939a5 100644 --- a/source4/heimdal/lib/gssapi/release_name.c +++ b/source4/heimdal/lib/gssapi/krb5/release_name.c @@ -31,20 +31,25 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: release_name.c,v 1.7 2003/03/16 17:52:48 lha Exp $"); +RCSID("$Id: release_name.c,v 1.10 2006/10/07 22:15:26 lha Exp $"); -OM_uint32 gss_release_name +OM_uint32 _gsskrb5_release_name (OM_uint32 * minor_status, gss_name_t * input_name ) { + krb5_principal name = (krb5_principal)*input_name; + GSSAPI_KRB5_INIT (); + if (minor_status) *minor_status = 0; - krb5_free_principal(gssapi_krb5_context, - *input_name); + *input_name = GSS_C_NO_NAME; + + krb5_free_principal(_gsskrb5_context, name); + return GSS_S_COMPLETE; } diff --git a/source4/heimdal/lib/gssapi/release_oid_set.c b/source4/heimdal/lib/gssapi/krb5/release_oid_set.c index 04eb01565f..a9f79a3082 100644 --- a/source4/heimdal/lib/gssapi/release_oid_set.c +++ b/source4/heimdal/lib/gssapi/krb5/release_oid_set.c @@ -31,11 +31,11 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: release_oid_set.c,v 1.5 2003/03/16 17:53:25 lha Exp $"); +RCSID("$Id: release_oid_set.c,v 1.7 2006/10/07 22:15:30 lha Exp $"); -OM_uint32 gss_release_oid_set +OM_uint32 _gsskrb5_release_oid_set (OM_uint32 * minor_status, gss_OID_set * set ) diff --git a/source4/heimdal/lib/gssapi/sequence.c b/source4/heimdal/lib/gssapi/krb5/sequence.c index 35a9b924af..3014edd04d 100755 --- a/source4/heimdal/lib/gssapi/sequence.c +++ b/source4/heimdal/lib/gssapi/krb5/sequence.c @@ -31,9 +31,9 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: sequence.c,v 1.6 2006/04/12 17:43:39 lha Exp $"); +RCSID("$Id: sequence.c,v 1.8 2006/10/07 22:15:32 lha Exp $"); #define DEFAULT_JITTER_WINDOW 20 @@ -159,8 +159,8 @@ _gssapi_msg_order_check(struct gss_msg_order *o, OM_uint32 seq_num) r = (o->flags & (GSS_C_REPLAY_FLAG|GSS_C_SEQUENCE_FLAG))==GSS_C_REPLAY_FLAG; - /* sequence number larger than largest sequence number - * or smaller than the first sequence number */ + /* sequence number larger then largest sequence number + * or smaller then the first sequence number */ if (seq_num > o->elem[0] || seq_num < o->first_seq || o->length == 0) diff --git a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c new file mode 100644 index 0000000000..5807ef0166 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: set_cred_option.c,v 1.4 2006/10/24 20:14:13 lha Exp $"); + +static gss_OID_desc gss_krb5_import_cred_x_oid_desc = +{9, (void *)"\x2b\x06\x01\x04\x01\xa9\x4a\x13\x04"}; /* XXX */ + +gss_OID GSS_KRB5_IMPORT_CRED_X = &gss_krb5_import_cred_x_oid_desc; + +static OM_uint32 +import_cred(OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_buffer_t value) +{ + OM_uint32 major_stat; + krb5_error_code ret; + krb5_principal keytab_principal = NULL; + krb5_keytab keytab = NULL; + krb5_storage *sp = NULL; + krb5_ccache id = NULL; + char *str; + + if (cred_handle == NULL || *cred_handle != GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + + sp = krb5_storage_from_mem(value->value, value->length); + if (sp == NULL) { + *minor_status = 0; + return GSS_S_FAILURE; + } + + /* credential cache name */ + ret = krb5_ret_string(sp, &str); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + if (str[0]) { + ret = krb5_cc_resolve(_gsskrb5_context, str, &id); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + } + free(str); + str = NULL; + + /* keytab principal name */ + ret = krb5_ret_string(sp, &str); + if (ret == 0 && str[0]) + ret = krb5_parse_name(_gsskrb5_context, str, &keytab_principal); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + free(str); + str = NULL; + + /* keytab principal */ + ret = krb5_ret_string(sp, &str); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + if (str[0]) { + ret = krb5_kt_resolve(_gsskrb5_context, str, &keytab); + if (ret) { + *minor_status = ret; + major_stat = GSS_S_FAILURE; + goto out; + } + } + free(str); + str = NULL; + + major_stat = _gsskrb5_import_cred(minor_status, id, keytab_principal, + keytab, cred_handle); +out: + if (id) + krb5_cc_close(_gsskrb5_context, id); + if (keytab_principal) + krb5_free_principal(_gsskrb5_context, keytab_principal); + if (keytab) + krb5_kt_close(_gsskrb5_context, keytab); + if (str) + free(str); + if (sp) + krb5_storage_free(sp); + + return major_stat; +} + + +OM_uint32 +_gsskrb5_set_cred_option + (OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + GSSAPI_KRB5_INIT (); + + if (value == GSS_C_NO_BUFFER) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (gss_oid_equal(desired_object, GSS_KRB5_IMPORT_CRED_X)) { + return import_cred(minor_status, cred_handle, value); + } + + *minor_status = EINVAL; + return GSS_S_FAILURE; +} diff --git a/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c b/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c new file mode 100644 index 0000000000..67f5e8e722 --- /dev/null +++ b/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * glue routine for _gsskrb5_inquire_sec_context_by_oid + */ + +#include "krb5/gsskrb5_locl.h" + +RCSID("$Id: set_sec_context_option.c,v 1.6 2006/10/20 18:58:22 lha Exp $"); + +static OM_uint32 +get_bool(OM_uint32 *minor_status, + const gss_buffer_t value, + int *flag) +{ + if (value->value == NULL || value->length != 1) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + *flag = *((const char *)value->value) != 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +_gsskrb5_set_sec_context_option + (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + OM_uint32 maj_stat; + + GSSAPI_KRB5_INIT (); + + if (value == GSS_C_NO_BUFFER) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (gss_oid_equal(desired_object, GSS_KRB5_COMPAT_DES3_MIC_X)) { + gsskrb5_ctx ctx; + int flag; + + if (*context_handle == GSS_C_NO_CONTEXT) { + *minor_status = EINVAL; + return GSS_S_NO_CONTEXT; + } + + maj_stat = get_bool(minor_status, value, &flag); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + ctx = (gsskrb5_ctx)*context_handle; + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + if (flag) + ctx->more_flags |= COMPAT_OLD_DES3; + else + ctx->more_flags &= ~COMPAT_OLD_DES3; + ctx->more_flags |= COMPAT_OLD_DES3_SELECTED; + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_COMPLETE; + } else if (gss_oid_equal(desired_object, GSS_KRB5_SET_DNS_CANONICALIZE_X)) { + int flag; + + maj_stat = get_bool(minor_status, value, &flag); + if (maj_stat != GSS_S_COMPLETE) + return maj_stat; + + krb5_set_dns_canonicalize_hostname(_gsskrb5_context, flag); + return GSS_S_COMPLETE; + + } else if (gss_oid_equal(desired_object, GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X)) { + char *str; + + if (value == NULL || value->length == 0) { + str = NULL; + } else { + str = malloc(value->length + 1); + if (str) { + *minor_status = 0; + return GSS_S_UNAVAILABLE; + } + memcpy(str, value->value, value->length); + str[value->length] = '\0'; + } + + _gsskrb5_register_acceptor_identity(str); + free(str); + + *minor_status = 0; + return GSS_S_COMPLETE; + + } else if (gss_oid_equal(desired_object, GSS_KRB5_SEND_TO_KDC_X)) { + + if (value == NULL || value->length == 0) { + krb5_set_send_to_kdc_func(_gsskrb5_context, NULL, NULL); + } else { + struct gsskrb5_send_to_kdc c; + + if (value->length != sizeof(c)) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + memcpy(&c, value->value, sizeof(c)); + krb5_set_send_to_kdc_func(_gsskrb5_context, + (krb5_send_to_kdc_func)c.func, + c.ptr); + } + + *minor_status = 0; + return GSS_S_COMPLETE; + } + + + *minor_status = EINVAL; + return GSS_S_FAILURE; +} diff --git a/source4/heimdal/lib/gssapi/test_oid_set_member.c b/source4/heimdal/lib/gssapi/krb5/test_oid_set_member.c index e747c5acc1..5a0ac4418f 100644 --- a/source4/heimdal/lib/gssapi/test_oid_set_member.c +++ b/source4/heimdal/lib/gssapi/krb5/test_oid_set_member.c @@ -31,25 +31,25 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: test_oid_set_member.c,v 1.5 2003/03/16 17:54:06 lha Exp $"); +RCSID("$Id: test_oid_set_member.c,v 1.7 2006/10/07 22:15:50 lha Exp $"); -OM_uint32 gss_test_oid_set_member ( - OM_uint32 * minor_status, +OM_uint32 _gsskrb5_test_oid_set_member + (OM_uint32 * minor_status, const gss_OID member, const gss_OID_set set, int * present ) { - size_t i; + size_t i; - *minor_status = 0; - *present = 0; - for (i = 0; i < set->count; ++i) - if (gss_oid_equal(member, &set->elements[i]) != 0) { - *present = 1; - break; - } - return GSS_S_COMPLETE; + *minor_status = 0; + *present = 0; + for (i = 0; i < set->count; ++i) + if (gss_oid_equal(member, &set->elements[i]) != 0) { + *present = 1; + break; + } + return GSS_S_COMPLETE; } diff --git a/source4/heimdal/lib/gssapi/unwrap.c b/source4/heimdal/lib/gssapi/krb5/unwrap.c index c358c1aa24..758390080c 100644 --- a/source4/heimdal/lib/gssapi/unwrap.c +++ b/source4/heimdal/lib/gssapi/krb5/unwrap.c @@ -31,14 +31,14 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: unwrap.c,v 1.34 2005/04/27 17:50:40 lha Exp $"); +RCSID("$Id: unwrap.c,v 1.38 2006/10/18 15:59:28 lha Exp $"); static OM_uint32 unwrap_des (OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, const gss_buffer_t input_message_buffer, gss_buffer_t output_message_buffer, int * conf_state, @@ -54,14 +54,14 @@ unwrap_des DES_cblock deskey; DES_cblock zero; int i; - int32_t seq_number; + uint32_t seq_number; size_t padlength; OM_uint32 ret; int cstate; int cmp; p = input_message_buffer->value; - ret = gssapi_krb5_verify_header (&p, + ret = _gsskrb5_verify_header (&p, input_message_buffer->length, "\x02\x01", GSS_KRB5_MECHANISM); @@ -138,7 +138,7 @@ unwrap_des memset (&schedule, 0, sizeof(schedule)); seq = p; - gssapi_decode_om_uint32(seq, &seq_number); + _gsskrb5_decode_om_uint32(seq, &seq_number); if (context_handle->more_flags & LOCAL) cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); @@ -174,7 +174,7 @@ unwrap_des static OM_uint32 unwrap_des3 (OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, const gss_buffer_t input_message_buffer, gss_buffer_t output_message_buffer, int * conf_state, @@ -187,7 +187,7 @@ unwrap_des3 u_char *seq; krb5_data seq_data; u_char cksum[20]; - int32_t seq_number; + uint32_t seq_number; size_t padlength; OM_uint32 ret; int cstate; @@ -196,7 +196,7 @@ unwrap_des3 int cmp; p = input_message_buffer->value; - ret = gssapi_krb5_verify_header (&p, + ret = _gsskrb5_verify_header (&p, input_message_buffer->length, "\x02\x01", GSS_KRB5_MECHANISM); @@ -226,18 +226,18 @@ unwrap_des3 /* decrypt data */ krb5_data tmp; - ret = krb5_crypto_init(gssapi_krb5_context, key, + ret = krb5_crypto_init(_gsskrb5_context, key, ETYPE_DES3_CBC_NONE, &crypto); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; return GSS_S_FAILURE; } - ret = krb5_decrypt(gssapi_krb5_context, crypto, KRB5_KU_USAGE_SEAL, + ret = krb5_decrypt(_gsskrb5_context, crypto, KRB5_KU_USAGE_SEAL, p, input_message_buffer->length - len, &tmp); - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; return GSS_S_FAILURE; } @@ -259,10 +259,10 @@ unwrap_des3 p -= 28; - ret = krb5_crypto_init(gssapi_krb5_context, key, + ret = krb5_crypto_init(_gsskrb5_context, key, ETYPE_DES3_CBC_NONE, &crypto); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_FAILURE; @@ -271,15 +271,15 @@ unwrap_des3 DES_cblock ivec; memcpy(&ivec, p + 8, 8); - ret = krb5_decrypt_ivec (gssapi_krb5_context, + ret = krb5_decrypt_ivec (_gsskrb5_context, crypto, KRB5_KU_USAGE_SEQ, p, 8, &seq_data, &ivec); } - krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_crypto_destroy (_gsskrb5_context, crypto); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_FAILURE; @@ -292,7 +292,7 @@ unwrap_des3 } seq = seq_data.data; - gssapi_decode_om_uint32(seq, &seq_number); + _gsskrb5_decode_om_uint32(seq, &seq_number); if (context_handle->more_flags & LOCAL) cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); @@ -325,21 +325,21 @@ unwrap_des3 csum.checksum.length = 20; csum.checksum.data = cksum; - ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto); + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; return GSS_S_FAILURE; } - ret = krb5_verify_checksum (gssapi_krb5_context, crypto, + ret = krb5_verify_checksum (_gsskrb5_context, crypto, KRB5_KU_USAGE_SIGN, p + 20, input_message_buffer->length - len + 8, &csum); - krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_crypto_destroy (_gsskrb5_context, crypto); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; return GSS_S_FAILURE; } @@ -357,7 +357,7 @@ unwrap_des3 return GSS_S_COMPLETE; } -OM_uint32 gss_unwrap +OM_uint32 _gsskrb5_unwrap (OM_uint32 * minor_status, const gss_ctx_id_t context_handle, const gss_buffer_t input_message_buffer, @@ -369,45 +369,48 @@ OM_uint32 gss_unwrap krb5_keyblock *key; OM_uint32 ret; krb5_keytype keytype; + gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle; output_message_buffer->value = NULL; output_message_buffer->length = 0; if (qop_state != NULL) *qop_state = GSS_C_QOP_DEFAULT; - ret = gss_krb5_get_subkey(context_handle, &key); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; return GSS_S_FAILURE; } - krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype); + krb5_enctype_to_keytype (_gsskrb5_context, key->keytype, &keytype); *minor_status = 0; switch (keytype) { case KEYTYPE_DES : - ret = unwrap_des (minor_status, context_handle, + ret = unwrap_des (minor_status, ctx, input_message_buffer, output_message_buffer, conf_state, qop_state, key); break; case KEYTYPE_DES3 : - ret = unwrap_des3 (minor_status, context_handle, + ret = unwrap_des3 (minor_status, ctx, input_message_buffer, output_message_buffer, conf_state, qop_state, key); break; case KEYTYPE_ARCFOUR: case KEYTYPE_ARCFOUR_56: - ret = _gssapi_unwrap_arcfour (minor_status, context_handle, + ret = _gssapi_unwrap_arcfour (minor_status, ctx, input_message_buffer, output_message_buffer, conf_state, qop_state, key); break; default : - ret = _gssapi_unwrap_cfx (minor_status, context_handle, + ret = _gssapi_unwrap_cfx (minor_status, ctx, input_message_buffer, output_message_buffer, conf_state, qop_state, key); break; } - krb5_free_keyblock (gssapi_krb5_context, key); + krb5_free_keyblock (_gsskrb5_context, key); return ret; } diff --git a/source4/heimdal/lib/gssapi/verify_mic.c b/source4/heimdal/lib/gssapi/krb5/verify_mic.c index 7b7d437e99..920937cafc 100644 --- a/source4/heimdal/lib/gssapi/verify_mic.c +++ b/source4/heimdal/lib/gssapi/krb5/verify_mic.c @@ -31,14 +31,14 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: verify_mic.c,v 1.32 2005/04/27 17:51:04 lha Exp $"); +RCSID("$Id: verify_mic.c,v 1.36 2006/10/18 15:59:30 lha Exp $"); static OM_uint32 verify_mic_des (OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, const gss_buffer_t message_buffer, const gss_buffer_t token_buffer, gss_qop_t * qop_state, @@ -52,12 +52,12 @@ verify_mic_des DES_key_schedule schedule; DES_cblock zero; DES_cblock deskey; - int32_t seq_number; + uint32_t seq_number; OM_uint32 ret; int cmp; p = token_buffer->value; - ret = gssapi_krb5_verify_header (&p, + ret = _gsskrb5_verify_header (&p, token_buffer->length, type, GSS_KRB5_MECHANISM); @@ -104,7 +104,7 @@ verify_mic_des memset (&schedule, 0, sizeof(schedule)); seq = p; - gssapi_decode_om_uint32(seq, &seq_number); + _gsskrb5_decode_om_uint32(seq, &seq_number); if (context_handle->more_flags & LOCAL) cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); @@ -130,7 +130,7 @@ verify_mic_des static OM_uint32 verify_mic_des3 (OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, const gss_buffer_t message_buffer, const gss_buffer_t token_buffer, gss_qop_t * qop_state, @@ -140,7 +140,7 @@ verify_mic_des3 { u_char *p; u_char *seq; - int32_t seq_number; + uint32_t seq_number; OM_uint32 ret; krb5_crypto crypto; krb5_data seq_data; @@ -150,7 +150,7 @@ verify_mic_des3 char ivec[8]; p = token_buffer->value; - ret = gssapi_krb5_verify_header (&p, + ret = _gsskrb5_verify_header (&p, token_buffer->length, type, GSS_KRB5_MECHANISM); @@ -164,10 +164,10 @@ verify_mic_des3 return GSS_S_BAD_MIC; p += 4; - ret = krb5_crypto_init(gssapi_krb5_context, key, + ret = krb5_crypto_init(_gsskrb5_context, key, ETYPE_DES3_CBC_NONE, &crypto); if (ret){ - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; return GSS_S_FAILURE; } @@ -180,14 +180,14 @@ retry: else memcpy(ivec, p + 8, 8); - ret = krb5_decrypt_ivec (gssapi_krb5_context, + ret = krb5_decrypt_ivec (_gsskrb5_context, crypto, KRB5_KU_USAGE_SEQ, p, 8, &seq_data, ivec); if (ret) { if (docompat++) { - gssapi_krb5_set_error_string (); - krb5_crypto_destroy (gssapi_krb5_context, crypto); + _gsskrb5_set_error_string (); + krb5_crypto_destroy (_gsskrb5_context, crypto); *minor_status = ret; return GSS_S_FAILURE; } else @@ -197,7 +197,7 @@ retry: if (seq_data.length != 8) { krb5_data_free (&seq_data); if (docompat++) { - krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_crypto_destroy (_gsskrb5_context, crypto); return GSS_S_BAD_MIC; } else goto retry; @@ -206,7 +206,7 @@ retry: HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); seq = seq_data.data; - gssapi_decode_om_uint32(seq, &seq_number); + _gsskrb5_decode_om_uint32(seq, &seq_number); if (context_handle->more_flags & LOCAL) cmp = memcmp(&seq[4], "\xff\xff\xff\xff", 4); @@ -215,7 +215,7 @@ retry: krb5_data_free (&seq_data); if (cmp != 0) { - krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_crypto_destroy (_gsskrb5_context, crypto); *minor_status = 0; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_BAD_MIC; @@ -223,7 +223,7 @@ retry: ret = _gssapi_msg_order_check(context_handle->order, seq_number); if (ret) { - krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_crypto_destroy (_gsskrb5_context, crypto); *minor_status = 0; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return ret; @@ -233,7 +233,7 @@ retry: tmp = malloc (message_buffer->length + 8); if (tmp == NULL) { - krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_crypto_destroy (_gsskrb5_context, crypto); HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); *minor_status = ENOMEM; return GSS_S_FAILURE; @@ -246,28 +246,28 @@ retry: csum.checksum.length = 20; csum.checksum.data = p + 8; - ret = krb5_verify_checksum (gssapi_krb5_context, crypto, + ret = krb5_verify_checksum (_gsskrb5_context, crypto, KRB5_KU_USAGE_SIGN, tmp, message_buffer->length + 8, &csum); free (tmp); if (ret) { - gssapi_krb5_set_error_string (); - krb5_crypto_destroy (gssapi_krb5_context, crypto); + _gsskrb5_set_error_string (); + krb5_crypto_destroy (_gsskrb5_context, crypto); *minor_status = ret; HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); return GSS_S_BAD_MIC; } HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_crypto_destroy (_gsskrb5_context, crypto); return GSS_S_COMPLETE; } OM_uint32 -gss_verify_mic_internal +_gsskrb5_verify_mic_internal (OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx context_handle, const gss_buffer_t message_buffer, const gss_buffer_t token_buffer, gss_qop_t * qop_state, @@ -278,14 +278,16 @@ gss_verify_mic_internal OM_uint32 ret; krb5_keytype keytype; - ret = gss_krb5_get_subkey(context_handle, &key); + HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(context_handle, &key); + HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; return GSS_S_FAILURE; } *minor_status = 0; - krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype); + krb5_enctype_to_keytype (_gsskrb5_context, key->keytype, &keytype); switch (keytype) { case KEYTYPE_DES : ret = verify_mic_des (minor_status, context_handle, @@ -309,13 +311,13 @@ gss_verify_mic_internal key); break; } - krb5_free_keyblock (gssapi_krb5_context, key); + krb5_free_keyblock (_gsskrb5_context, key); return ret; } OM_uint32 -gss_verify_mic +_gsskrb5_verify_mic (OM_uint32 * minor_status, const gss_ctx_id_t context_handle, const gss_buffer_t message_buffer, @@ -328,9 +330,10 @@ gss_verify_mic if (qop_state != NULL) *qop_state = GSS_C_QOP_DEFAULT; - ret = gss_verify_mic_internal(minor_status, context_handle, - message_buffer, token_buffer, - qop_state, "\x01\x01"); + ret = _gsskrb5_verify_mic_internal(minor_status, + (gsskrb5_ctx)context_handle, + message_buffer, token_buffer, + qop_state, "\x01\x01"); return ret; } diff --git a/source4/heimdal/lib/gssapi/wrap.c b/source4/heimdal/lib/gssapi/krb5/wrap.c index 7072ca2754..8514137999 100644 --- a/source4/heimdal/lib/gssapi/wrap.c +++ b/source4/heimdal/lib/gssapi/krb5/wrap.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,110 +31,84 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" +#include "krb5/gsskrb5_locl.h" -RCSID("$Id: wrap.c,v 1.33 2006/05/05 10:27:36 lha Exp $"); +RCSID("$Id: wrap.c,v 1.37 2006/10/18 15:59:33 lha Exp $"); -OM_uint32 -gsskrb5_get_initiator_subkey(OM_uint32 *minor_status, - gss_ctx_id_t context_handle, - gss_buffer_t key) +/* + * Return initiator subkey, or if that doesn't exists, the subkey. + */ + +krb5_error_code +_gsskrb5i_get_initiator_subkey(const gsskrb5_ctx ctx, krb5_keyblock **key) { krb5_error_code ret; - krb5_keyblock *skey = NULL; - - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - if (context_handle->more_flags & LOCAL) { - ret = krb5_auth_con_getlocalsubkey(gssapi_krb5_context, - context_handle->auth_context, - &skey); - if (ret) { - *minor_status = ret; - return GSS_KRB5_S_KG_NO_SUBKEY; /* XXX */ - } - + *key = NULL; + + if (ctx->more_flags & LOCAL) { + ret = krb5_auth_con_getlocalsubkey(_gsskrb5_context, + ctx->auth_context, + key); } else { - ret = krb5_auth_con_getremotesubkey(gssapi_krb5_context, - context_handle->auth_context, - &skey); - if (ret) { - *minor_status = ret; - return GSS_KRB5_S_KG_NO_SUBKEY; /* XXX */ - } - + ret = krb5_auth_con_getremotesubkey(_gsskrb5_context, + ctx->auth_context, + key); } - - /* If there was no subkey, perhaps try this... */ - if(skey == NULL) { - krb5_auth_con_getkey(gssapi_krb5_context, - context_handle->auth_context, - &skey); + if (*key == NULL) + ret = krb5_auth_con_getkey(_gsskrb5_context, + ctx->auth_context, + key); + if (*key == NULL) { + _gsskrb5_set_status("No initiator subkey available"); + return GSS_KRB5_S_KG_NO_SUBKEY; } + return ret; +} - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); +krb5_error_code +_gsskrb5i_get_acceptor_subkey(const gsskrb5_ctx ctx, krb5_keyblock **key) +{ + krb5_error_code ret; + *key = NULL; - /* ensure never to segfault */ - if(skey == NULL) { - return GSS_KRB5_S_KG_NO_SUBKEY; /* XXX */ + if (ctx->more_flags & LOCAL) { + ret = krb5_auth_con_getremotesubkey(_gsskrb5_context, + ctx->auth_context, + key); + } else { + ret = krb5_auth_con_getlocalsubkey(_gsskrb5_context, + ctx->auth_context, + key); } - - key->length = skey->keyvalue.length; - key->value = malloc (key->length); - if (!key->value) { - krb5_free_keyblock(gssapi_krb5_context, skey); - *minor_status = ENOMEM; - return GSS_S_FAILURE; + if (*key == NULL) { + _gsskrb5_set_status("No acceptor subkey available"); + return GSS_KRB5_S_KG_NO_SUBKEY; } - memcpy(key->value, skey->keyvalue.data, key->length); - krb5_free_keyblock(gssapi_krb5_context, skey); - return 0; + return ret; } OM_uint32 -gss_krb5_get_subkey(const gss_ctx_id_t context_handle, - krb5_keyblock **key) +_gsskrb5i_get_token_key(const gsskrb5_ctx ctx, krb5_keyblock **key) { - krb5_keyblock *skey = NULL; - - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - if (context_handle->more_flags & LOCAL) { - krb5_auth_con_getremotesubkey(gssapi_krb5_context, - context_handle->auth_context, - &skey); - } else { - krb5_auth_con_getlocalsubkey(gssapi_krb5_context, - context_handle->auth_context, - &skey); + _gsskrb5i_get_acceptor_subkey(ctx, key); + if(*key == NULL) { + /* + * Only use the initiator subkey or ticket session key if an + * acceptor subkey was not required. + */ + if ((ctx->more_flags & ACCEPTOR_SUBKEY) == 0) + _gsskrb5i_get_initiator_subkey(ctx, key); } - /* - * Only use the initiator subkey or ticket session key if - * an acceptor subkey was not required. - */ - if (skey == NULL && - (context_handle->more_flags & ACCEPTOR_SUBKEY) == 0) { - if (context_handle->more_flags & LOCAL) { - krb5_auth_con_getlocalsubkey(gssapi_krb5_context, - context_handle->auth_context, - &skey); - } else { - krb5_auth_con_getremotesubkey(gssapi_krb5_context, - context_handle->auth_context, - &skey); - } - if(skey == NULL) - krb5_auth_con_getkey(gssapi_krb5_context, - context_handle->auth_context, - &skey); + if (*key == NULL) { + _gsskrb5_set_status("No token key available"); + return GSS_KRB5_S_KG_NO_SUBKEY; } - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); - if(skey == NULL) - return GSS_KRB5_S_KG_NO_SUBKEY; /* XXX */ - *key = skey; + _gsskrb5_clear_status(); return 0; } static OM_uint32 -sub_wrap_size_limit ( +sub_wrap_size ( OM_uint32 req_output_size, OM_uint32 * max_input_size, int blocksize, @@ -145,7 +119,7 @@ sub_wrap_size_limit ( len = 8 + req_output_size + blocksize + extrasize; - gssapi_krb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); + _gsskrb5_encap_length(len, &len, &total_len, GSS_KRB5_MECHANISM); total_len -= req_output_size; /* token length */ if (total_len < req_output_size) { @@ -158,7 +132,7 @@ sub_wrap_size_limit ( } OM_uint32 -gss_wrap_size_limit ( +_gsskrb5_wrap_size_limit ( OM_uint32 * minor_status, const gss_ctx_id_t context_handle, int conf_req_flag, @@ -170,118 +144,38 @@ gss_wrap_size_limit ( krb5_keyblock *key; OM_uint32 ret; krb5_keytype keytype; - OM_uint32 output_size; - OM_uint32 blocksize; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; - ret = gss_krb5_get_subkey(context_handle, &key); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; return GSS_S_FAILURE; } - krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype); + krb5_enctype_to_keytype (_gsskrb5_context, key->keytype, &keytype); switch (keytype) { case KEYTYPE_DES : - ret = sub_wrap_size_limit(req_output_size, max_input_size, 8, 22); - break; - case KEYTYPE_DES3 : - ret = sub_wrap_size_limit(req_output_size, max_input_size, 8, 34); + ret = sub_wrap_size(req_output_size, max_input_size, 8, 22); break; case KEYTYPE_ARCFOUR: case KEYTYPE_ARCFOUR_56: - ret = _gssapi_wrap_size_arcfour(minor_status, context_handle, + ret = _gssapi_wrap_size_arcfour(minor_status, ctx, conf_req_flag, qop_req, - req_output_size, &output_size, - &blocksize, key); - - if (output_size > req_output_size) { - *max_input_size = req_output_size - (output_size - req_output_size); - (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); - } else { - *max_input_size = 0; - } - break; - default : - ret = _gssapi_wrap_size_cfx(minor_status, context_handle, - conf_req_flag, qop_req, - req_output_size, &output_size, - &blocksize, key); - if (output_size > req_output_size) { - *max_input_size = req_output_size - (output_size - req_output_size); - (*max_input_size) &= (~(OM_uint32)(blocksize - 1)); - } else { - *max_input_size = 0; - } - break; - } - krb5_free_keyblock (gssapi_krb5_context, key); - *minor_status = 0; - return ret; -} - -static OM_uint32 -sub_wrap_size ( - OM_uint32 req_input_size, - OM_uint32 * output_size, - int blocksize, - int extrasize - ) -{ - size_t len, total_len, padlength, datalen; - - padlength = blocksize - (req_input_size % blocksize); - datalen = req_input_size + padlength + 8; - len = datalen + extrasize; - gssapi_krb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); - - *output_size = total_len; - - return GSS_S_COMPLETE; -} - -OM_uint32 -gsskrb5_wrap_size ( - OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, - int conf_req_flag, - gss_qop_t qop_req, - OM_uint32 req_input_size, - OM_uint32 * output_size - ) -{ - krb5_keyblock *key; - OM_uint32 ret, padlen; - krb5_keytype keytype; - - ret = gss_krb5_get_subkey(context_handle, &key); - if (ret) { - gssapi_krb5_set_error_string (); - *minor_status = ret; - return GSS_S_FAILURE; - } - krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype); - - switch (keytype) { - case KEYTYPE_DES : - ret = sub_wrap_size(req_input_size, output_size, 8, 22); + req_output_size, max_input_size, key); break; case KEYTYPE_DES3 : - ret = sub_wrap_size(req_input_size, output_size, 8, 34); - break; - case KEYTYPE_ARCFOUR: - case KEYTYPE_ARCFOUR_56: - ret = _gssapi_wrap_size_arcfour(minor_status, context_handle, - conf_req_flag, qop_req, - req_input_size, output_size, &padlen, key); + ret = sub_wrap_size(req_output_size, max_input_size, 8, 34); break; default : - ret = _gssapi_wrap_size_cfx(minor_status, context_handle, + ret = _gssapi_wrap_size_cfx(minor_status, ctx, conf_req_flag, qop_req, - req_input_size, output_size, &padlen, key); + req_output_size, max_input_size, key); break; } - krb5_free_keyblock (gssapi_krb5_context, key); + krb5_free_keyblock (_gsskrb5_context, key); *minor_status = 0; return ret; } @@ -289,7 +183,7 @@ gsskrb5_wrap_size ( static OM_uint32 wrap_des (OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx ctx, int conf_req_flag, gss_qop_t qop_req, const gss_buffer_t input_message_buffer, @@ -311,7 +205,7 @@ wrap_des padlength = 8 - (input_message_buffer->length % 8); datalen = input_message_buffer->length + padlength + 8; len = datalen + 22; - gssapi_krb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); + _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); output_message_buffer->length = total_len; output_message_buffer->value = malloc (total_len); @@ -321,7 +215,7 @@ wrap_des return GSS_S_FAILURE; } - p = gssapi_krb5_make_header(output_message_buffer->value, + p = _gsskrb5_make_header(output_message_buffer->value, len, "\x02\x01", /* TOK_ID */ GSS_KRB5_MECHANISM); @@ -363,9 +257,9 @@ wrap_des memcpy (p - 8, hash, 8); /* sequence number */ - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); - krb5_auth_con_getlocalseqnumber (gssapi_krb5_context, - context_handle->auth_context, + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, + ctx->auth_context, &seq_number); p -= 16; @@ -374,17 +268,17 @@ wrap_des p[2] = (seq_number >> 16) & 0xFF; p[3] = (seq_number >> 24) & 0xFF; memset (p + 4, - (context_handle->more_flags & LOCAL) ? 0 : 0xFF, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, 4); DES_set_key (&deskey, &schedule); DES_cbc_encrypt ((void *)p, (void *)p, 8, &schedule, (DES_cblock *)(p + 8), DES_ENCRYPT); - krb5_auth_con_setlocalseqnumber (gssapi_krb5_context, - context_handle->auth_context, + krb5_auth_con_setlocalseqnumber (_gsskrb5_context, + ctx->auth_context, ++seq_number); - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); /* encrypt the data */ p += 16; @@ -415,7 +309,7 @@ wrap_des static OM_uint32 wrap_des3 (OM_uint32 * minor_status, - const gss_ctx_id_t context_handle, + const gsskrb5_ctx ctx, int conf_req_flag, gss_qop_t qop_req, const gss_buffer_t input_message_buffer, @@ -436,7 +330,7 @@ wrap_des3 padlength = 8 - (input_message_buffer->length % 8); datalen = input_message_buffer->length + padlength + 8; len = datalen + 34; - gssapi_krb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); + _gsskrb5_encap_length (len, &len, &total_len, GSS_KRB5_MECHANISM); output_message_buffer->length = total_len; output_message_buffer->value = malloc (total_len); @@ -446,7 +340,7 @@ wrap_des3 return GSS_S_FAILURE; } - p = gssapi_krb5_make_header(output_message_buffer->value, + p = _gsskrb5_make_header(output_message_buffer->value, len, "\x02\x01", /* TOK_ID */ GSS_KRB5_MECHANISM); @@ -472,9 +366,9 @@ wrap_des3 input_message_buffer->length); memset (p + 28 + 8 + input_message_buffer->length, padlength, padlength); - ret = krb5_crypto_init(gssapi_krb5_context, key, 0, &crypto); + ret = krb5_crypto_init(_gsskrb5_context, key, 0, &crypto); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); free (output_message_buffer->value); output_message_buffer->length = 0; output_message_buffer->value = NULL; @@ -482,16 +376,16 @@ wrap_des3 return GSS_S_FAILURE; } - ret = krb5_create_checksum (gssapi_krb5_context, + ret = krb5_create_checksum (_gsskrb5_context, crypto, KRB5_KU_USAGE_SIGN, 0, p + 20, datalen + 8, &cksum); - krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_crypto_destroy (_gsskrb5_context, crypto); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); free (output_message_buffer->value); output_message_buffer->length = 0; output_message_buffer->value = NULL; @@ -505,10 +399,10 @@ wrap_des3 memcpy (p + 8, cksum.checksum.data, cksum.checksum.length); free_Checksum (&cksum); - HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); /* sequence number */ - krb5_auth_con_getlocalseqnumber (gssapi_krb5_context, - context_handle->auth_context, + krb5_auth_con_getlocalseqnumber (_gsskrb5_context, + ctx->auth_context, &seq_number); seq[0] = (seq_number >> 0) & 0xFF; @@ -516,11 +410,11 @@ wrap_des3 seq[2] = (seq_number >> 16) & 0xFF; seq[3] = (seq_number >> 24) & 0xFF; memset (seq + 4, - (context_handle->more_flags & LOCAL) ? 0 : 0xFF, + (ctx->more_flags & LOCAL) ? 0 : 0xFF, 4); - ret = krb5_crypto_init(gssapi_krb5_context, key, ETYPE_DES3_CBC_NONE, + ret = krb5_crypto_init(_gsskrb5_context, key, ETYPE_DES3_CBC_NONE, &crypto); if (ret) { free (output_message_buffer->value); @@ -534,15 +428,15 @@ wrap_des3 DES_cblock ivec; memcpy (&ivec, p + 8, 8); - ret = krb5_encrypt_ivec (gssapi_krb5_context, + ret = krb5_encrypt_ivec (_gsskrb5_context, crypto, KRB5_KU_USAGE_SEQ, seq, 8, &encdata, &ivec); } - krb5_crypto_destroy (gssapi_krb5_context, crypto); + krb5_crypto_destroy (_gsskrb5_context, crypto); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); free (output_message_buffer->value); output_message_buffer->length = 0; output_message_buffer->value = NULL; @@ -555,10 +449,10 @@ wrap_des3 memcpy (p, encdata.data, encdata.length); krb5_data_free (&encdata); - krb5_auth_con_setlocalseqnumber (gssapi_krb5_context, - context_handle->auth_context, + krb5_auth_con_setlocalseqnumber (_gsskrb5_context, + ctx->auth_context, ++seq_number); - HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); /* encrypt the data */ p += 28; @@ -566,21 +460,21 @@ wrap_des3 if(conf_req_flag) { krb5_data tmp; - ret = krb5_crypto_init(gssapi_krb5_context, key, + ret = krb5_crypto_init(_gsskrb5_context, key, ETYPE_DES3_CBC_NONE, &crypto); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); free (output_message_buffer->value); output_message_buffer->length = 0; output_message_buffer->value = NULL; *minor_status = ret; return GSS_S_FAILURE; } - ret = krb5_encrypt(gssapi_krb5_context, crypto, KRB5_KU_USAGE_SEAL, + ret = krb5_encrypt(_gsskrb5_context, crypto, KRB5_KU_USAGE_SEAL, p, datalen, &tmp); - krb5_crypto_destroy(gssapi_krb5_context, crypto); + krb5_crypto_destroy(_gsskrb5_context, crypto); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); free (output_message_buffer->value); output_message_buffer->length = 0; output_message_buffer->value = NULL; @@ -598,7 +492,7 @@ wrap_des3 return GSS_S_COMPLETE; } -OM_uint32 gss_wrap +OM_uint32 _gsskrb5_wrap (OM_uint32 * minor_status, const gss_ctx_id_t context_handle, int conf_req_flag, @@ -611,38 +505,41 @@ OM_uint32 gss_wrap krb5_keyblock *key; OM_uint32 ret; krb5_keytype keytype; + const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle; - ret = gss_krb5_get_subkey(context_handle, &key); + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + ret = _gsskrb5i_get_token_key(ctx, &key); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); if (ret) { - gssapi_krb5_set_error_string (); + _gsskrb5_set_error_string (); *minor_status = ret; return GSS_S_FAILURE; } - krb5_enctype_to_keytype (gssapi_krb5_context, key->keytype, &keytype); + krb5_enctype_to_keytype (_gsskrb5_context, key->keytype, &keytype); switch (keytype) { case KEYTYPE_DES : - ret = wrap_des (minor_status, context_handle, conf_req_flag, + ret = wrap_des (minor_status, ctx, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer, key); break; case KEYTYPE_DES3 : - ret = wrap_des3 (minor_status, context_handle, conf_req_flag, + ret = wrap_des3 (minor_status, ctx, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer, key); break; case KEYTYPE_ARCFOUR: case KEYTYPE_ARCFOUR_56: - ret = _gssapi_wrap_arcfour (minor_status, context_handle, conf_req_flag, + ret = _gssapi_wrap_arcfour (minor_status, ctx, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer, key); break; default : - ret = _gssapi_wrap_cfx (minor_status, context_handle, conf_req_flag, + ret = _gssapi_wrap_cfx (minor_status, ctx, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer, key); break; } - krb5_free_keyblock (gssapi_krb5_context, key); + krb5_free_keyblock (_gsskrb5_context, key); return ret; } diff --git a/source4/heimdal/lib/gssapi/mech/context.h b/source4/heimdal/lib/gssapi/mech/context.h new file mode 100644 index 0000000000..7a215dd7d8 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/context.h @@ -0,0 +1,35 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/context.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + * $Id: context.h,v 1.2 2006/06/28 09:00:25 lha Exp $ + */ + +#include <gssapi_mech.h> + +struct _gss_context { + gssapi_mech_interface gc_mech; + gss_ctx_id_t gc_ctx; +}; diff --git a/source4/heimdal/lib/gssapi/mech/cred.h b/source4/heimdal/lib/gssapi/mech/cred.h new file mode 100644 index 0000000000..df89e79727 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/cred.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/cred.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + * $Id: cred.h,v 1.3 2006/10/05 18:26:54 lha Exp $ + */ + +struct _gss_mechanism_cred { + SLIST_ENTRY(_gss_mechanism_cred) gmc_link; + gssapi_mech_interface gmc_mech; /* mechanism ops for MC */ + gss_OID gmc_mech_oid; /* mechanism oid for MC */ + gss_cred_id_t gmc_cred; /* underlying MC */ +}; +SLIST_HEAD(_gss_mechanism_cred_list, _gss_mechanism_cred); + +struct _gss_cred { + gss_cred_usage_t gc_usage; + struct _gss_mechanism_cred_list gc_mc; +}; + diff --git a/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c new file mode 100644 index 0000000000..4d634bf20f --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c @@ -0,0 +1,223 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_accept_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_accept_sec_context.c,v 1.6 2006/10/25 00:45:12 lha Exp $"); + +OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t *src_name, + gss_OID *mech_type, + gss_buffer_t output_token, + OM_uint32 *ret_flags, + OM_uint32 *time_rec, + gss_cred_id_t *delegated_cred_handle) +{ + OM_uint32 major_status, mech_ret_flags; + gssapi_mech_interface m; + struct _gss_context *ctx = (struct _gss_context *) *context_handle; + struct _gss_cred *cred = (struct _gss_cred *) acceptor_cred_handle; + struct _gss_mechanism_cred *mc; + gss_cred_id_t acceptor_mc, delegated_mc; + gss_name_t src_mn; + int allocated_ctx; + + *minor_status = 0; + if (src_name) *src_name = 0; + if (mech_type) *mech_type = 0; + if (ret_flags) *ret_flags = 0; + if (time_rec) *time_rec = 0; + if (delegated_cred_handle) *delegated_cred_handle = 0; + output_token->length = 0; + output_token->value = 0; + + /* + * If this is the first call (*context_handle is NULL), we must + * parse the input token to figure out the mechanism to use. + */ + if (*context_handle == GSS_C_NO_CONTEXT) { + unsigned char *p = input_token->value; + size_t len = input_token->length; + size_t a, b; + gss_OID_desc mech_oid; + + /* + * Token must start with [APPLICATION 0] SEQUENCE. + * But if it doesn't assume its DCE-STYLE Kerberos! + */ + if (len == 0) + return (GSS_S_DEFECTIVE_TOKEN); + if (*p != 0x60) { + mech_oid = *GSS_KRB5_MECHANISM; + } else { + p++; + len--; + + /* + * Decode the length and make sure it agrees with the + * token length. + */ + if (len == 0) + return (GSS_S_DEFECTIVE_TOKEN); + if ((*p & 0x80) == 0) { + a = *p; + p++; + len--; + } else { + b = *p & 0x7f; + p++; + len--; + if (len < b) + return (GSS_S_DEFECTIVE_TOKEN); + a = 0; + while (b) { + a = (a << 8) | *p; + p++; + len--; + b--; + } + } + if (a != len) + return (GSS_S_DEFECTIVE_TOKEN); + + /* + * Decode the OID for the mechanism. Simplify life by + * assuming that the OID length is less than 128 bytes. + */ + if (len < 2 || *p != 0x06) + return (GSS_S_DEFECTIVE_TOKEN); + if ((p[1] & 0x80) || p[1] > (len - 2)) + return (GSS_S_DEFECTIVE_TOKEN); + mech_oid.length = p[1]; + p += 2; + len -= 2; + mech_oid.elements = p; + } + /* + * Now that we have a mechanism, we can find the + * implementation. + */ + ctx = malloc(sizeof(struct _gss_context)); + if (!ctx) { + *minor_status = ENOMEM; + return (GSS_S_DEFECTIVE_TOKEN); + } + memset(ctx, 0, sizeof(struct _gss_context)); + m = ctx->gc_mech = __gss_get_mechanism(&mech_oid); + if (!m) { + free(ctx); + return (GSS_S_BAD_MECH); + } + allocated_ctx = 1; + } else { + m = ctx->gc_mech; + allocated_ctx = 0; + } + + if (cred) { + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) + if (mc->gmc_mech == m) + break; + if (!mc) + return (GSS_S_BAD_MECH); + acceptor_mc = mc->gmc_cred; + } else { + acceptor_mc = GSS_C_NO_CREDENTIAL; + } + delegated_mc = GSS_C_NO_CREDENTIAL; + + mech_ret_flags = 0; + major_status = m->gm_accept_sec_context(minor_status, + &ctx->gc_ctx, + acceptor_mc, + input_token, + input_chan_bindings, + &src_mn, + mech_type, + output_token, + &mech_ret_flags, + time_rec, + &delegated_mc); + if (major_status != GSS_S_COMPLETE && + major_status != GSS_S_CONTINUE_NEEDED) + return (major_status); + + if (!src_name) { + m->gm_release_name(minor_status, &src_mn); + } else { + /* + * Make a new name and mark it as an MN. + */ + struct _gss_name *name = _gss_make_name(m, src_mn); + + if (!name) { + m->gm_release_name(minor_status, &src_mn); + return (GSS_S_FAILURE); + } + *src_name = (gss_name_t) name; + } + + if (mech_ret_flags & GSS_C_DELEG_FLAG) { + if (!delegated_cred_handle) { + m->gm_release_cred(minor_status, &delegated_mc); + *ret_flags &= ~GSS_C_DELEG_FLAG; + } else { + struct _gss_cred *dcred; + struct _gss_mechanism_cred *dmc; + + dcred = malloc(sizeof(struct _gss_cred)); + if (!dcred) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + SLIST_INIT(&dcred->gc_mc); + dmc = malloc(sizeof(struct _gss_mechanism_cred)); + if (!dmc) { + free(dcred); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + m->gm_inquire_cred(minor_status, delegated_mc, + 0, 0, &dcred->gc_usage, 0); + dmc->gmc_mech = m; + dmc->gmc_mech_oid = &m->gm_mech_oid; + dmc->gmc_cred = delegated_mc; + SLIST_INSERT_HEAD(&dcred->gc_mc, dmc, gmc_link); + + *delegated_cred_handle = (gss_cred_id_t) dcred; + } + } + + if (ret_flags) + *ret_flags = mech_ret_flags; + *context_handle = (gss_ctx_id_t) ctx; + return (major_status); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c b/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c new file mode 100644 index 0000000000..0b3554c0fa --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c @@ -0,0 +1,164 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_acquire_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_acquire_cred.c,v 1.4 2006/10/25 00:44:55 lha Exp $"); + +OM_uint32 +gss_acquire_cred(OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *time_rec) +{ + OM_uint32 major_status; + gss_OID_set mechs = desired_mechs; + gss_OID_set_desc set; + struct _gss_name *name = (struct _gss_name *) desired_name; + gssapi_mech_interface m; + struct _gss_cred *cred; + struct _gss_mechanism_cred *mc; + OM_uint32 min_time, cred_time; + int i; + + _gss_load_mech(); + + /* + * First make sure that at least one of the requested + * mechanisms is one that we support. + */ + if (mechs) { + for (i = 0; i < mechs->count; i++) { + int t; + gss_test_oid_set_member(minor_status, + &mechs->elements[i], _gss_mech_oids, &t); + if (t) + break; + } + if (i == mechs->count) { + *output_cred_handle = 0; + *minor_status = 0; + return (GSS_S_BAD_MECH); + } + } + + if (actual_mechs) { + major_status = gss_create_empty_oid_set(minor_status, + actual_mechs); + if (major_status) + return (major_status); + } + + cred = malloc(sizeof(struct _gss_cred)); + if (!cred) { + if (actual_mechs) + gss_release_oid_set(minor_status, actual_mechs); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + cred->gc_usage = cred_usage; + SLIST_INIT(&cred->gc_mc); + + if (mechs == GSS_C_NO_OID_SET) + mechs = _gss_mech_oids; + + set.count = 1; + min_time = GSS_C_INDEFINITE; + for (i = 0; i < mechs->count; i++) { + struct _gss_mechanism_name *mn = NULL; + + m = __gss_get_mechanism(&mechs->elements[i]); + if (!m) + continue; + + if (desired_name != GSS_C_NO_NAME) { + mn = _gss_find_mn(name, &mechs->elements[i]); + if (!mn) + continue; + } + + mc = malloc(sizeof(struct _gss_mechanism_cred)); + if (!mc) { + continue; + } + SLIST_INIT(&cred->gc_mc); + mc->gmc_mech = m; + mc->gmc_mech_oid = &m->gm_mech_oid; + + /* + * XXX Probably need to do something with actual_mechs. + */ + set.elements = &mechs->elements[i]; + major_status = m->gm_acquire_cred(minor_status, + (desired_name != GSS_C_NO_NAME + ? mn->gmn_name : GSS_C_NO_NAME), + time_req, &set, cred_usage, + &mc->gmc_cred, NULL, &cred_time); + if (major_status) { + free(mc); + continue; + } + if (cred_time < min_time) + min_time = cred_time; + + if (actual_mechs) { + major_status = gss_add_oid_set_member(minor_status, + mc->gmc_mech_oid, actual_mechs); + if (major_status) { + m->gm_release_cred(minor_status, + &mc->gmc_cred); + free(mc); + continue; + } + } + + SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); + } + + /* + * If we didn't manage to create a single credential, return + * an error. + */ + if (!SLIST_FIRST(&cred->gc_mc)) { + free(cred); + if (actual_mechs) + gss_release_oid_set(minor_status, actual_mechs); + *output_cred_handle = 0; + *minor_status = 0; + return (GSS_S_NO_CRED); + } + + if (time_rec) + *time_rec = min_time; + *output_cred_handle = (gss_cred_id_t) cred; + *minor_status = 0; + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_add_cred.c b/source4/heimdal/lib/gssapi/mech/gss_add_cred.c new file mode 100644 index 0000000000..beffd54e29 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_add_cred.c @@ -0,0 +1,175 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_add_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_add_cred.c,v 1.3 2006/06/29 08:23:53 lha Exp $"); + +static struct _gss_mechanism_cred * +_gss_copy_cred(struct _gss_mechanism_cred *mc) +{ + struct _gss_mechanism_cred *new_mc; + gssapi_mech_interface m = mc->gmc_mech; + OM_uint32 major_status, minor_status; + gss_name_t name; + gss_cred_id_t cred; + OM_uint32 initiator_lifetime, acceptor_lifetime; + gss_cred_usage_t cred_usage; + + major_status = m->gm_inquire_cred_by_mech(&minor_status, + mc->gmc_cred, mc->gmc_mech_oid, + &name, &initiator_lifetime, &acceptor_lifetime, &cred_usage); + if (major_status) + return (0); + + major_status = m->gm_add_cred(&minor_status, + GSS_C_NO_CREDENTIAL, name, mc->gmc_mech_oid, + cred_usage, initiator_lifetime, acceptor_lifetime, + &cred, 0, 0, 0); + m->gm_release_name(&minor_status, &name); + + if (major_status) + return (0); + + new_mc = malloc(sizeof(struct _gss_mechanism_cred)); + if (!new_mc) { + m->gm_release_cred(&minor_status, &cred); + return (0); + } + new_mc->gmc_mech = m; + new_mc->gmc_mech_oid = &m->gm_mech_oid; + new_mc->gmc_cred = cred; + + return (new_mc); +} + +OM_uint32 +gss_add_cred(OM_uint32 *minor_status, + const gss_cred_id_t input_cred_handle, + const gss_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t *output_cred_handle, + gss_OID_set *actual_mechs, + OM_uint32 *initiator_time_rec, + OM_uint32 *acceptor_time_rec) +{ + OM_uint32 major_status; + gssapi_mech_interface m; + struct _gss_cred *cred = (struct _gss_cred *) input_cred_handle; + struct _gss_cred *new_cred; + gss_cred_id_t release_cred; + struct _gss_mechanism_cred *mc, *target_mc, *copy_mc; + struct _gss_mechanism_name *mn; + OM_uint32 junk; + + *output_cred_handle = 0; + *minor_status = 0; + + new_cred = malloc(sizeof(struct _gss_cred)); + if (!new_cred) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + new_cred->gc_usage = cred_usage; + SLIST_INIT(&new_cred->gc_mc); + + /* + * We go through all the mc attached to the input_cred_handle + * and check the mechanism. If it matches, we call + * gss_add_cred for that mechanism, otherwise we copy the mc + * to new_cred. + */ + target_mc = 0; + if (cred) { + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { + if (gss_oid_equal(mc->gmc_mech_oid, desired_mech)) { + target_mc = mc; + } + copy_mc = _gss_copy_cred(mc); + if (!copy_mc) { + release_cred = (gss_cred_id_t)new_cred; + gss_release_cred(&junk, &release_cred); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + SLIST_INSERT_HEAD(&new_cred->gc_mc, copy_mc, gmc_link); + } + } + + /* + * Figure out a suitable mn, if any. + */ + if (desired_name) { + mn = _gss_find_mn((struct _gss_name *) desired_name, + desired_mech); + if (!mn) { + free(new_cred); + return (GSS_S_BAD_NAME); + } + } else { + mn = 0; + } + + m = __gss_get_mechanism(desired_mech); + + mc = malloc(sizeof(struct _gss_mechanism_cred)); + if (!mc) { + release_cred = (gss_cred_id_t)new_cred; + gss_release_cred(&junk, &release_cred); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + mc->gmc_mech = m; + mc->gmc_mech_oid = &m->gm_mech_oid; + + major_status = m->gm_add_cred(minor_status, + target_mc ? target_mc->gmc_cred : GSS_C_NO_CREDENTIAL, + desired_name ? mn->gmn_name : GSS_C_NO_NAME, + desired_mech, + cred_usage, + initiator_time_req, + acceptor_time_req, + &mc->gmc_cred, + actual_mechs, + initiator_time_rec, + acceptor_time_rec); + + if (major_status) { + release_cred = (gss_cred_id_t)new_cred; + gss_release_cred(&junk, &release_cred); + free(mc); + return (major_status); + } + SLIST_INSERT_HEAD(&new_cred->gc_mc, mc, gmc_link); + *output_cred_handle = (gss_cred_id_t) new_cred; + + return (GSS_S_COMPLETE); +} + diff --git a/source4/heimdal/lib/gssapi/ccache_name.c b/source4/heimdal/lib/gssapi/mech/gss_add_oid_set_member.c index 3bebb83c1f..5806cec009 100755..100644 --- a/source4/heimdal/lib/gssapi/ccache_name.c +++ b/source4/heimdal/lib/gssapi/mech/gss_add_oid_set_member.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,50 +31,37 @@ * SUCH DAMAGE. */ -#include "gssapi_locl.h" - -RCSID("$Id: ccache_name.c,v 1.2 2005/06/16 20:38:49 lha Exp $"); - -char *last_out_name; +#include "mech_locl.h" +RCSID("$Id: gss_add_oid_set_member.c,v 1.3 2006/10/22 09:36:13 lha Exp $"); OM_uint32 -gss_krb5_ccache_name(OM_uint32 *minor_status, - const char *name, - const char **out_name) +gss_add_oid_set_member (OM_uint32 * minor_status, + const gss_OID member_oid, + gss_OID_set * oid_set) { - krb5_error_code kret; - - *minor_status = 0; + gss_OID tmp; + size_t n; + OM_uint32 res; + int present; - GSSAPI_KRB5_INIT(); + res = gss_test_oid_set_member(minor_status, member_oid, *oid_set, &present); + if (res != GSS_S_COMPLETE) + return res; - if (out_name) { - const char *n; - - if (last_out_name) { - free(last_out_name); - last_out_name = NULL; - } - - n = krb5_cc_default_name(gssapi_krb5_context); - if (n == NULL) { - *minor_status = ENOMEM; - gssapi_krb5_set_error_string (); - return GSS_S_FAILURE; - } - last_out_name = strdup(n); - if (last_out_name == NULL) { - *minor_status = ENOMEM; - return GSS_S_FAILURE; - } - *out_name = last_out_name; + if (present) { + *minor_status = 0; + return GSS_S_COMPLETE; } - kret = krb5_cc_set_default_name(gssapi_krb5_context, name); - if (kret) { - *minor_status = kret; - gssapi_krb5_set_error_string (); + n = (*oid_set)->count + 1; + tmp = realloc ((*oid_set)->elements, n * sizeof(gss_OID_desc)); + if (tmp == NULL) { + *minor_status = ENOMEM; return GSS_S_FAILURE; } + (*oid_set)->elements = tmp; + (*oid_set)->count = n; + (*oid_set)->elements[n-1] = *member_oid; + *minor_status = 0; return GSS_S_COMPLETE; } diff --git a/source4/heimdal/lib/gssapi/mech/gss_buffer_set.c b/source4/heimdal/lib/gssapi/mech/gss_buffer_set.c new file mode 100644 index 0000000000..9e9bd5e790 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_buffer_set.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +RCSID("$Id: gss_buffer_set.c,v 1.2 2006/10/24 21:53:02 lha Exp $"); + +OM_uint32 +gss_create_empty_buffer_set + (OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + gss_buffer_set_t set; + + set = (gss_buffer_set_desc *) malloc(sizeof(*set)); + if (set == GSS_C_NO_BUFFER_SET) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + set->count = 0; + set->elements = NULL; + + *buffer_set = set; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +gss_add_buffer_set_member + (OM_uint32 * minor_status, + const gss_buffer_t member_buffer, + gss_buffer_set_t *buffer_set) +{ + gss_buffer_set_t set; + gss_buffer_t p; + OM_uint32 ret; + + if (*buffer_set == GSS_C_NO_BUFFER_SET) { + ret = gss_create_empty_buffer_set(minor_status, + buffer_set); + if (ret) { + return ret; + } + } + + set = *buffer_set; + set->elements = realloc(set->elements, + (set->count + 1) * sizeof(set->elements[0])); + if (set->elements == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + p = &set->elements[set->count]; + + p->value = malloc(member_buffer->length); + if (p->value == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy(p->value, member_buffer->value, member_buffer->length); + p->length = member_buffer->length; + + set->count++; + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +gss_release_buffer_set(OM_uint32 * minor_status, + gss_buffer_set_t *buffer_set) +{ + int i; + OM_uint32 minor; + + *minor_status = 0; + + if (*buffer_set == GSS_C_NO_BUFFER_SET) + return GSS_S_COMPLETE; + + for (i = 0; i < (*buffer_set)->count; i++) + gss_release_buffer(&minor, &((*buffer_set)->elements[i])); + + free((*buffer_set)->elements); + + (*buffer_set)->elements = NULL; + (*buffer_set)->count = 0; + + free(*buffer_set); + *buffer_set = GSS_C_NO_BUFFER_SET; + + return GSS_S_COMPLETE; +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c b/source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c new file mode 100644 index 0000000000..38a464be46 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_canonicalize_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_canonicalize_name.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_canonicalize_name(OM_uint32 *minor_status, + const gss_name_t input_name, + const gss_OID mech_type, + gss_name_t *output_name) +{ + OM_uint32 major_status; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + gssapi_mech_interface m = __gss_get_mechanism(mech_type); + gss_name_t new_canonical_name; + + *minor_status = 0; + *output_name = 0; + + mn = _gss_find_mn(name, mech_type); + if (!mn) { + return (GSS_S_BAD_MECH); + } + + m = mn->gmn_mech; + major_status = m->gm_canonicalize_name(minor_status, + mn->gmn_name, mech_type, &new_canonical_name); + if (major_status) + return (major_status); + + /* + * Now we make a new name and mark it as an MN. + */ + *minor_status = 0; + name = malloc(sizeof(struct _gss_name)); + if (!name) { + m->gm_release_name(minor_status, &new_canonical_name); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + memset(name, 0, sizeof(struct _gss_name)); + + mn = malloc(sizeof(struct _gss_mechanism_name)); + if (!mn) { + m->gm_release_name(minor_status, &new_canonical_name); + free(name); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + SLIST_INIT(&name->gn_mn); + mn->gmn_mech = m; + mn->gmn_mech_oid = &m->gm_mech_oid; + mn->gmn_name = new_canonical_name; + SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); + + *output_name = (gss_name_t) name; + + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_compare_name.c b/source4/heimdal/lib/gssapi/mech/gss_compare_name.c new file mode 100644 index 0000000000..1068bfabf6 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_compare_name.c @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_compare_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_compare_name.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_compare_name(OM_uint32 *minor_status, + const gss_name_t name1_arg, + const gss_name_t name2_arg, + int *name_equal) +{ + struct _gss_name *name1 = (struct _gss_name *) name1_arg; + struct _gss_name *name2 = (struct _gss_name *) name2_arg; + + /* + * First check the implementation-independant name if both + * names have one. Otherwise, try to find common mechanism + * names and compare them. + */ + if (name1->gn_value.value && name2->gn_value.value) { + *name_equal = 1; + if (!gss_oid_equal(&name1->gn_type, &name2->gn_type)) { + *name_equal = 0; + } else if (name1->gn_value.length != name2->gn_value.length || + memcmp(name1->gn_value.value, name1->gn_value.value, + name1->gn_value.length)) { + *name_equal = 0; + } + } else { + struct _gss_mechanism_name *mn1; + struct _gss_mechanism_name *mn2; + + SLIST_FOREACH(mn1, &name1->gn_mn, gmn_link) { + mn2 = _gss_find_mn(name2, mn1->gmn_mech_oid); + if (mn2) { + return (mn1->gmn_mech->gm_compare_name( + minor_status, + mn1->gmn_name, + mn2->gmn_name, + name_equal)); + } + } + *name_equal = 0; + } + + *minor_status = 0; + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_context_time.c b/source4/heimdal/lib/gssapi/mech/gss_context_time.c new file mode 100644 index 0000000000..4b17381776 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_context_time.c @@ -0,0 +1,41 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_context_time.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_context_time.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_context_time(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + OM_uint32 *time_rec) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m = ctx->gc_mech; + + return (m->gm_context_time(minor_status, ctx->gc_ctx, time_rec)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_create_empty_oid_set.c b/source4/heimdal/lib/gssapi/mech/gss_create_empty_oid_set.c new file mode 100644 index 0000000000..7298ec9e83 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_create_empty_oid_set.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_create_empty_oid_set.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_create_empty_oid_set.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_create_empty_oid_set(OM_uint32 *minor_status, + gss_OID_set *oid_set) +{ + gss_OID_set set; + + *minor_status = 0; + *oid_set = 0; + + set = malloc(sizeof(gss_OID_set_desc)); + if (!set) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + + set->count = 0; + set->elements = 0; + *oid_set = set; + + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_decapsulate_token.c b/source4/heimdal/lib/gssapi/mech/gss_decapsulate_token.c new file mode 100644 index 0000000000..8ebb848188 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_decapsulate_token.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +RCSID("$Id: gss_decapsulate_token.c,v 1.2 2006/10/14 10:04:45 lha Exp $"); + +OM_uint32 +gss_decapsulate_token(gss_buffer_t input_token, + gss_OID oid, + gss_buffer_t output_token) +{ + GSSAPIContextToken ct; + heim_oid o; + OM_uint32 status; + int ret; + size_t size; + + output_token->length = 0; + output_token->value = NULL; + + ret = der_get_oid (oid->elements, oid->length, &o, &size); + if (ret) + return GSS_S_FAILURE; + + ret = decode_GSSAPIContextToken(input_token->value, input_token->length, + &ct, NULL); + if (ret) { + der_free_oid(&o); + return GSS_S_FAILURE; + } + + if (der_heim_oid_cmp(&ct.thisMech, &o) == 0) { + status = GSS_S_COMPLETE; + output_token->value = ct.innerContextToken.data; + output_token->length = ct.innerContextToken.length; + der_free_oid(&ct.thisMech); + } else { + free_GSSAPIContextToken(&ct); + status = GSS_S_FAILURE; + } + der_free_oid(&o); + + return status; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_delete_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_delete_sec_context.c new file mode 100644 index 0000000000..06ef8e6d09 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_delete_sec_context.c @@ -0,0 +1,58 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_delete_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_delete_sec_context.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_delete_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token) +{ + OM_uint32 major_status; + struct _gss_context *ctx = (struct _gss_context *) *context_handle; + + *minor_status = 0; + if (ctx) { + /* + * If we have an implementation ctx, delete it, + * otherwise fake an empty token. + */ + if (ctx->gc_ctx) { + major_status = ctx->gc_mech->gm_delete_sec_context( + minor_status, &ctx->gc_ctx, output_token); + } else if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = 0; + } + free(ctx); + *context_handle = 0; + } + + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_display_name.c b/source4/heimdal/lib/gssapi/mech/gss_display_name.c new file mode 100644 index 0000000000..79f62a7a4f --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_display_name.c @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_display_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_display_name.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_display_name(OM_uint32 *minor_status, + const gss_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID *output_name_type) +{ + OM_uint32 major_status; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + + /* + * If we know it, copy the buffer used to import the name in + * the first place. Otherwise, ask all the MNs in turn if + * they can display the thing. + */ + if (name->gn_value.value) { + output_name_buffer->value = malloc(name->gn_value.length); + if (!output_name_buffer->value) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + output_name_buffer->length = name->gn_value.length; + memcpy(output_name_buffer->value, name->gn_value.value, + output_name_buffer->length); + if (output_name_type) + *output_name_type = &name->gn_type; + + *minor_status = 0; + return (GSS_S_COMPLETE); + } else { + SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { + major_status = mn->gmn_mech->gm_display_name( + minor_status, mn->gmn_name, + output_name_buffer, + output_name_type); + if (major_status == GSS_S_COMPLETE) + return (GSS_S_COMPLETE); + } + } + + *minor_status = 0; + return (GSS_S_FAILURE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_display_status.c b/source4/heimdal/lib/gssapi/mech/gss_display_status.c new file mode 100644 index 0000000000..7871f5338b --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_display_status.c @@ -0,0 +1,184 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_display_status.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ +/* + * Copyright (c) 1998 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +RCSID("$Id: gss_display_status.c,v 1.4 2006/07/19 11:02:33 lha Exp $"); + +static const char * +calling_error(OM_uint32 v) +{ + static const char *msgs[] = { + NULL, /* 0 */ + "A required input parameter could not be read.", /* */ + "A required output parameter could not be written.", /* */ + "A parameter was malformed" + }; + + v >>= GSS_C_CALLING_ERROR_OFFSET; + + if (v == 0) + return ""; + else if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown calling error"; + else + return msgs[v]; +} + +static const char * +routine_error(OM_uint32 v) +{ + static const char *msgs[] = { + NULL, /* 0 */ + "An unsupported mechanism was requested", + "An invalid name was supplied", + "A supplied name was of an unsupported type", + "Incorrect channel bindings were supplied", + "An invalid status code was supplied", + "A token had an invalid MIC", + "No credentials were supplied, " + "or the credentials were unavailable or inaccessible.", + "No context has been established", + "A token was invalid", + "A credential was invalid", + "The referenced credentials have expired", + "The context has expired", + "Miscellaneous failure (see text)", + "The quality-of-protection requested could not be provide", + "The operation is forbidden by local security policy", + "The operation or option is not available", + "The requested credential element already exists", + "The provided name was not a mechanism name.", + }; + + v >>= GSS_C_ROUTINE_ERROR_OFFSET; + + if (v == 0) + return ""; + else if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown routine error"; + else + return msgs[v]; +} + +static const char * +supplementary_error(OM_uint32 v) +{ + static const char *msgs[] = { + "normal completion", + "continuation call to routine required", + "duplicate per-message token detected", + "timed-out per-message token detected", + "reordered (early) per-message token detected", + "skipped predecessor token(s) detected" + }; + + v >>= GSS_C_SUPPLEMENTARY_OFFSET; + + if (v >= sizeof(msgs)/sizeof(*msgs)) + return "unknown routine error"; + else + return msgs[v]; +} + + +OM_uint32 +gss_display_status(OM_uint32 *minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 *message_content, + gss_buffer_t status_string) +{ + OM_uint32 major_status; + + *minor_status = 0; + switch (status_type) { + case GSS_C_GSS_CODE: { + char *buf; + + if (GSS_SUPPLEMENTARY_INFO(status_value)) + asprintf(&buf, "%s", supplementary_error( + GSS_SUPPLEMENTARY_INFO(status_value))); + else + asprintf (&buf, "%s %s", + calling_error(GSS_CALLING_ERROR(status_value)), + routine_error(GSS_ROUTINE_ERROR(status_value))); + + status_string->length = strlen(buf); + status_string->value = buf; + + return GSS_S_COMPLETE; + } + case GSS_C_MECH_CODE: { + gssapi_mech_interface m; + m = __gss_get_mechanism(mech_type); + if (m) { + major_status = m->gm_display_status(minor_status, + status_value, status_type, mech_type, + message_content, status_string); + if (major_status == GSS_S_COMPLETE) + return (GSS_S_COMPLETE); + } + } + } + status_string->value = NULL; + status_string->length = 0; + return (GSS_S_BAD_STATUS); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c b/source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c new file mode 100644 index 0000000000..5ef828f472 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c @@ -0,0 +1,75 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_duplicate_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_duplicate_name.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 gss_duplicate_name(OM_uint32 *minor_status, + const gss_name_t src_name, + gss_name_t *dest_name) +{ + OM_uint32 major_status; + struct _gss_name *name = (struct _gss_name *) src_name; + struct _gss_name *new_name; + struct _gss_mechanism_name *mn; + + *minor_status = 0; + + /* + * If this name has a value (i.e. it didn't come from + * gss_canonicalize_name(), we re-import the thing. Otherwise, + * we make an empty name to hold the MN copy. + */ + if (name->gn_value.value) { + major_status = gss_import_name(minor_status, + &name->gn_value, &name->gn_type, dest_name); + if (major_status != GSS_S_COMPLETE) + return (major_status); + new_name = (struct _gss_name *) *dest_name; + } else { + new_name = malloc(sizeof(struct _gss_name)); + if (!new_name) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + memset(new_name, 0, sizeof(struct _gss_name)); + SLIST_INIT(&name->gn_mn); + *dest_name = (gss_name_t) new_name; + } + + /* + * Import the new name into any mechanisms listed in the + * original name. We could probably get away with only doing + * this if the original was canonical. + */ + SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { + _gss_find_mn(new_name, mn->gmn_mech_oid); + } + + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_duplicate_oid.c b/source4/heimdal/lib/gssapi/mech/gss_duplicate_oid.c new file mode 100644 index 0000000000..bfb0e75315 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_duplicate_oid.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +RCSID("$Id: gss_duplicate_oid.c,v 1.1 2006/06/28 09:07:07 lha Exp $"); + +OM_uint32 gss_duplicate_oid ( + OM_uint32 *minor_status, + gss_OID src_oid, + gss_OID *dest_oid + ) +{ + *minor_status = 0; + + if (src_oid == GSS_C_NO_OID) { + *dest_oid = GSS_C_NO_OID; + return GSS_S_COMPLETE; + } + + *dest_oid = malloc(sizeof(**dest_oid)); + if (*dest_oid == GSS_C_NO_OID) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + (*dest_oid)->elements = malloc(src_oid->length); + if ((*dest_oid)->elements == NULL) { + free(*dest_oid); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + memcpy((*dest_oid)->elements, src_oid->elements, src_oid->length); + (*dest_oid)->length = src_oid->length; + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_encapsulate_token.c b/source4/heimdal/lib/gssapi/mech/gss_encapsulate_token.c new file mode 100644 index 0000000000..d1285815ee --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_encapsulate_token.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +RCSID("$Id: gss_encapsulate_token.c,v 1.2 2006/10/14 10:05:12 lha Exp $"); + +OM_uint32 +gss_encapsulate_token(gss_buffer_t input_token, + gss_OID oid, + gss_buffer_t output_token) +{ + GSSAPIContextToken ct; + int ret; + size_t size; + + ret = der_get_oid (oid->elements, oid->length, &ct.thisMech, &size); + if (ret) { + output_token->value = NULL; + output_token->length = 0; + return GSS_S_FAILURE; + } + + ct.innerContextToken.data = input_token->value; + ct.innerContextToken.length = input_token->length; + + ASN1_MALLOC_ENCODE(GSSAPIContextToken, + output_token->value, output_token->length, + &ct, &size, ret); + der_free_oid(&ct.thisMech); + if (ret) { + output_token->length = 0; + output_token->value = NULL; + return GSS_S_FAILURE; + } + if (output_token->length != size) + abort(); + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_export_name.c b/source4/heimdal/lib/gssapi/mech/gss_export_name.c new file mode 100644 index 0000000000..bc1c39c8ee --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_export_name.c @@ -0,0 +1,56 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_export_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_export_name.c,v 1.3 2006/07/05 22:41:57 lha Exp $"); + +OM_uint32 +gss_export_name(OM_uint32 *minor_status, + const gss_name_t input_name, + gss_buffer_t exported_name) +{ + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mechanism_name *mn; + + exported_name->value = NULL; + exported_name->length = 0; + + /* + * If this name already has any attached MNs, export the first + * one, otherwise export based on the first mechanism in our + * list. + */ + mn = SLIST_FIRST(&name->gn_mn); + if (!mn) { + *minor_status = 0; + return (GSS_S_NAME_NOT_MN); + } + + return mn->gmn_mech->gm_export_name(minor_status, + mn->gmn_name, exported_name); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_export_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_export_sec_context.c new file mode 100644 index 0000000000..1acc72b33d --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_export_sec_context.c @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_export_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_export_sec_context.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_export_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t interprocess_token) +{ + OM_uint32 major_status; + struct _gss_context *ctx = (struct _gss_context *) *context_handle; + gssapi_mech_interface m = ctx->gc_mech; + gss_buffer_desc buf; + + major_status = m->gm_export_sec_context(minor_status, + &ctx->gc_ctx, &buf); + + if (major_status == GSS_S_COMPLETE) { + unsigned char *p; + + free(ctx); + *context_handle = GSS_C_NO_CONTEXT; + interprocess_token->length = buf.length + + 2 + m->gm_mech_oid.length; + interprocess_token->value = malloc(interprocess_token->length); + if (!interprocess_token->value) { + /* + * We are in trouble here - the context is + * already gone. This is allowed as long as we + * set the caller's context_handle to + * GSS_C_NO_CONTEXT, which we did above. + * Return GSS_S_FAILURE. + */ + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + p = interprocess_token->value; + p[0] = m->gm_mech_oid.length >> 8; + p[1] = m->gm_mech_oid.length; + memcpy(p + 2, m->gm_mech_oid.elements, m->gm_mech_oid.length); + memcpy(p + 2 + m->gm_mech_oid.length, buf.value, buf.length); + gss_release_buffer(minor_status, &buf); + } + + return (major_status); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_get_mic.c b/source4/heimdal/lib/gssapi/mech/gss_get_mic.c new file mode 100644 index 0000000000..e9a8f294a4 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_get_mic.c @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_get_mic.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_get_mic.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_get_mic(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m = ctx->gc_mech; + + return (m->gm_get_mic(minor_status, ctx->gc_ctx, qop_req, + message_buffer, message_token)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_import_name.c b/source4/heimdal/lib/gssapi/mech/gss_import_name.c new file mode 100644 index 0000000000..9684301ba4 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_import_name.c @@ -0,0 +1,214 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_import_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_import_name.c,v 1.3 2006/06/29 21:23:13 lha Exp $"); + +static OM_uint32 +_gss_import_export_name(OM_uint32 *minor_status, + const gss_buffer_t input_name_buffer, + gss_name_t *output_name) +{ + OM_uint32 major_status; + unsigned char *p = input_name_buffer->value; + size_t len = input_name_buffer->length; + size_t t; + gss_OID_desc mech_oid; + gssapi_mech_interface m; + struct _gss_name *name; + gss_name_t new_canonical_name; + + *minor_status = 0; + *output_name = 0; + + /* + * Make sure that TOK_ID is {4, 1}. + */ + if (len < 2) + return (GSS_S_BAD_NAME); + if (p[0] != 4 || p[1] != 1) + return (GSS_S_BAD_NAME); + p += 2; + len -= 2; + + /* + * Get the mech length and the name length and sanity + * check the size of of the buffer. + */ + if (len < 2) + return (GSS_S_BAD_NAME); + t = (p[0] << 8) + p[1]; + p += 2; + len -= 2; + + /* + * Check the DER encoded OID to make sure it agrees with the + * length we just decoded. + */ + if (p[0] != 6) /* 6=OID */ + return (GSS_S_BAD_NAME); + p++; + len--; + t--; + if (p[0] & 0x80) { + int digits = p[0]; + p++; + len--; + t--; + mech_oid.length = 0; + while (digits--) { + mech_oid.length = (mech_oid.length << 8) | p[0]; + p++; + len--; + t--; + } + } else { + mech_oid.length = p[0]; + p++; + len--; + t--; + } + if (mech_oid.length != t) + return (GSS_S_BAD_NAME); + + mech_oid.elements = p; + + if (len < t + 4) + return (GSS_S_BAD_NAME); + p += t; + len -= t; + + t = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; + p += 4; + len -= 4; + + if (len != t) + return (GSS_S_BAD_NAME); + + m = __gss_get_mechanism(&mech_oid); + if (!m) + return (GSS_S_BAD_MECH); + + /* + * Ask the mechanism to import the name. + */ + major_status = m->gm_import_name(minor_status, + input_name_buffer, GSS_C_NT_EXPORT_NAME, &new_canonical_name); + + /* + * Now we make a new name and mark it as an MN. + */ + name = _gss_make_name(m, new_canonical_name); + if (!name) { + m->gm_release_name(minor_status, &new_canonical_name); + return (GSS_S_FAILURE); + } + + *output_name = (gss_name_t) name; + + *minor_status = 0; + return (GSS_S_COMPLETE); +} + +OM_uint32 +gss_import_name(OM_uint32 *minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t *output_name) +{ + gss_OID name_type = input_name_type; + OM_uint32 major_status; + struct _gss_name *name; + + if (input_name_buffer->length == 0) { + *minor_status = 0; + *output_name = 0; + return (GSS_S_BAD_NAME); + } + + /* + * Use GSS_NT_USER_NAME as default name type. + */ + if (name_type == GSS_C_NO_OID) + name_type = GSS_C_NT_USER_NAME; + + /* + * If this is an exported name, we need to parse it to find + * the mechanism and then import it as an MN. See RFC 2743 + * section 3.2 for a description of the format. + */ + if (gss_oid_equal(name_type, GSS_C_NT_EXPORT_NAME)) { + return _gss_import_export_name(minor_status, + input_name_buffer, output_name); + } + + /* + * Only allow certain name types. This is pretty bogus - we + * should figure out the list of supported name types using + * gss_inquire_names_for_mech. + */ + if (!gss_oid_equal(name_type, GSS_C_NT_USER_NAME) + && !gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME) + && !gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME) + && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X) + && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE) + && !gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS) + && !gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) { + *minor_status = 0; + *output_name = 0; + return (GSS_S_BAD_NAMETYPE); + } + + *minor_status = 0; + name = malloc(sizeof(struct _gss_name)); + if (!name) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + memset(name, 0, sizeof(struct _gss_name)); + + major_status = _gss_copy_oid(minor_status, + name_type, &name->gn_type); + if (major_status) { + free(name); + return (GSS_S_FAILURE); + } + + major_status = _gss_copy_buffer(minor_status, + input_name_buffer, &name->gn_value); + if (major_status) { + gss_name_t rname = (gss_name_t)name; + gss_release_name(minor_status, &rname); + return (GSS_S_FAILURE); + } + + SLIST_INIT(&name->gn_mn); + + *output_name = (gss_name_t) name; + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_import_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_import_sec_context.c new file mode 100644 index 0000000000..5466f97cf4 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_import_sec_context.c @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_import_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_import_sec_context.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_import_sec_context(OM_uint32 *minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle) +{ + OM_uint32 major_status; + gssapi_mech_interface m; + struct _gss_context *ctx; + gss_OID_desc mech_oid; + gss_buffer_desc buf; + unsigned char *p; + size_t len; + + *minor_status = 0; + *context_handle = 0; + + /* + * We added an oid to the front of the token in + * gss_export_sec_context. + */ + p = interprocess_token->value; + len = interprocess_token->length; + if (len < 2) + return (GSS_S_DEFECTIVE_TOKEN); + mech_oid.length = (p[0] << 8) | p[1]; + if (len < mech_oid.length + 2) + return (GSS_S_DEFECTIVE_TOKEN); + mech_oid.elements = p + 2; + buf.length = len - 2 - mech_oid.length; + buf.value = p + 2 + mech_oid.length; + + m = __gss_get_mechanism(&mech_oid); + if (!m) + return (GSS_S_DEFECTIVE_TOKEN); + + ctx = malloc(sizeof(struct _gss_context)); + if (!ctx) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + ctx->gc_mech = m; + major_status = m->gm_import_sec_context(minor_status, + &buf, &ctx->gc_ctx); + if (major_status != GSS_S_COMPLETE) { + free(ctx); + } else { + *context_handle = (gss_ctx_id_t) ctx; + } + + return (major_status); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_indicate_mechs.c b/source4/heimdal/lib/gssapi/mech/gss_indicate_mechs.c new file mode 100644 index 0000000000..0da6c48834 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_indicate_mechs.c @@ -0,0 +1,65 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_indicate_mechs.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_indicate_mechs.c,v 1.3 2006/07/05 22:36:49 lha Exp $"); + +OM_uint32 +gss_indicate_mechs(OM_uint32 *minor_status, + gss_OID_set *mech_set) +{ + struct _gss_mech_switch *m; + OM_uint32 major_status; + gss_OID_set set; + int i; + + _gss_load_mech(); + + major_status = gss_create_empty_oid_set(minor_status, mech_set); + if (major_status) + return (major_status); + + SLIST_FOREACH(m, &_gss_mechs, gm_link) { + if (m->gm_mech.gm_indicate_mechs) { + major_status = m->gm_mech.gm_indicate_mechs( + minor_status, &set); + if (major_status) + continue; + for (i = 0; i < set->count; i++) + major_status = gss_add_oid_set_member( + minor_status, &set->elements[i], mech_set); + gss_release_oid_set(minor_status, &set); + } else { + major_status = gss_add_oid_set_member( + minor_status, &m->gm_mech_oid, mech_set); + } + } + + *minor_status = 0; + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_init_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_init_sec_context.c new file mode 100644 index 0000000000..ccaf91ba9d --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_init_sec_context.c @@ -0,0 +1,133 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_init_sec_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_init_sec_context.c,v 1.3 2006/07/06 22:30:09 lha Exp $"); + +OM_uint32 +gss_init_sec_context(OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID input_mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec) +{ + OM_uint32 major_status; + gssapi_mech_interface m; + struct _gss_name *name = (struct _gss_name *) target_name; + struct _gss_mechanism_name *mn; + struct _gss_context *ctx = (struct _gss_context *) *context_handle; + struct _gss_cred *cred = (struct _gss_cred *) initiator_cred_handle; + struct _gss_mechanism_cred *mc; + gss_cred_id_t cred_handle; + int allocated_ctx; + gss_OID mech_type = input_mech_type; + + *minor_status = 0; + + /* + * If we haven't allocated a context yet, do so now and lookup + * the mechanism switch table. If we have one already, make + * sure we use the same mechanism switch as before. + */ + if (!ctx) { + if (mech_type == NULL) + mech_type = GSS_KRB5_MECHANISM; + + ctx = malloc(sizeof(struct _gss_context)); + if (!ctx) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + memset(ctx, 0, sizeof(struct _gss_context)); + m = ctx->gc_mech = __gss_get_mechanism(mech_type); + if (!m) { + free(ctx); + return (GSS_S_BAD_MECH); + } + allocated_ctx = 1; + } else { + m = ctx->gc_mech; + mech_type = &ctx->gc_mech->gm_mech_oid; + allocated_ctx = 0; + } + + /* + * Find the MN for this mechanism. + */ + mn = _gss_find_mn(name, mech_type); + if (mn == NULL) { + if (allocated_ctx) + free(ctx); + return GSS_S_BAD_NAME; + } + + /* + * If we have a cred, find the cred for this mechanism. + */ + cred_handle = GSS_C_NO_CREDENTIAL; + if (cred) { + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { + if (gss_oid_equal(mech_type, mc->gmc_mech_oid)) { + cred_handle = mc->gmc_cred; + break; + } + } + } + + major_status = m->gm_init_sec_context(minor_status, + cred_handle, + &ctx->gc_ctx, + mn->gmn_name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + + if (major_status != GSS_S_COMPLETE + && major_status != GSS_S_CONTINUE_NEEDED) { + if (allocated_ctx) + free(ctx); + } else { + *context_handle = (gss_ctx_id_t) ctx; + } + + return (major_status); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_context.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_context.c new file mode 100644 index 0000000000..88bbb3941f --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_context.c @@ -0,0 +1,85 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_inquire_context.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_inquire_context.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_inquire_context(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_name_t *src_name, + gss_name_t *targ_name, + OM_uint32 *lifetime_rec, + gss_OID *mech_type, + OM_uint32 *ctx_flags, + int *locally_initiated, + int *open) +{ + OM_uint32 major_status; + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m = ctx->gc_mech; + struct _gss_name *name; + gss_name_t src_mn, targ_mn; + + major_status = m->gm_inquire_context(minor_status, + ctx->gc_ctx, + src_name ? &src_mn : 0, + targ_name ? &targ_mn : 0, + lifetime_rec, + mech_type, + ctx_flags, + locally_initiated, + open); + + if (src_name) *src_name = 0; + if (targ_name) *targ_name = 0; + + if (major_status != GSS_S_COMPLETE) { + return (major_status); + } + + if (src_name) { + name = _gss_make_name(m, src_mn); + if (!name) { + minor_status = 0; + return (GSS_S_FAILURE); + } + *src_name = (gss_name_t) name; + } + + if (targ_name) { + name = _gss_make_name(m, targ_mn); + if (!name) { + minor_status = 0; + return (GSS_S_FAILURE); + } + *targ_name = (gss_name_t) name; + } + + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_cred.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred.c new file mode 100644 index 0000000000..223140205d --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred.c @@ -0,0 +1,168 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_inquire_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_inquire_cred.c,v 1.5 2006/07/20 02:03:18 lha Exp $"); + +OM_uint32 +gss_inquire_cred(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + gss_name_t *name_ret, + OM_uint32 *lifetime, + gss_cred_usage_t *cred_usage, + gss_OID_set *mechanisms) +{ + OM_uint32 major_status; + struct _gss_mech_switch *m; + struct _gss_cred *cred = (struct _gss_cred *) cred_handle; + struct _gss_name *name; + struct _gss_mechanism_name *mn; + OM_uint32 min_lifetime; + int found = 0; + + _gss_load_mech(); + + *minor_status = 0; + if (name_ret) + *name_ret = 0; + if (lifetime) + *lifetime = 0; + if (cred_usage) + *cred_usage = 0; + + if (name_ret) { + name = malloc(sizeof(struct _gss_name)); + if (!name) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + memset(name, 0, sizeof(struct _gss_name)); + SLIST_INIT(&name->gn_mn); + } else { + name = 0; + } + + if (mechanisms) { + major_status = gss_create_empty_oid_set(minor_status, + mechanisms); + if (major_status) { + if (name) free(name); + return (major_status); + } + } + + min_lifetime = GSS_C_INDEFINITE; + if (cred) { + struct _gss_mechanism_cred *mc; + + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { + gss_name_t mc_name; + OM_uint32 mc_lifetime; + + major_status = mc->gmc_mech->gm_inquire_cred(minor_status, + mc->gmc_cred, &mc_name, &mc_lifetime, NULL, NULL); + if (major_status) + continue; + + if (name) { + mn = malloc(sizeof(struct _gss_mechanism_name)); + if (!mn) { + mc->gmc_mech->gm_release_name(minor_status, + &mc_name); + continue; + } + mn->gmn_mech = mc->gmc_mech; + mn->gmn_mech_oid = mc->gmc_mech_oid; + mn->gmn_name = mc_name; + SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); + } else { + mc->gmc_mech->gm_release_name(minor_status, + &mc_name); + } + + if (mc_lifetime < min_lifetime) + min_lifetime = mc_lifetime; + + if (mechanisms) + gss_add_oid_set_member(minor_status, + mc->gmc_mech_oid, mechanisms); + found++; + } + } else { + SLIST_FOREACH(m, &_gss_mechs, gm_link) { + gss_name_t mc_name; + OM_uint32 mc_lifetime; + + major_status = m->gm_mech.gm_inquire_cred(minor_status, + GSS_C_NO_CREDENTIAL, &mc_name, &mc_lifetime, + cred_usage, NULL); + if (major_status) + continue; + + if (name && mc_name) { + mn = malloc( + sizeof(struct _gss_mechanism_name)); + if (!mn) { + m->gm_mech.gm_release_name( + minor_status, &mc_name); + continue; + } + mn->gmn_mech = &m->gm_mech; + mn->gmn_mech_oid = &m->gm_mech_oid; + mn->gmn_name = mc_name; + SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); + } else if (mc_name) { + m->gm_mech.gm_release_name(minor_status, + &mc_name); + } + + if (mc_lifetime < min_lifetime) + min_lifetime = mc_lifetime; + + if (mechanisms) + gss_add_oid_set_member(minor_status, + &m->gm_mech_oid, mechanisms); + found++; + } + } + + if (found == 0) { + gss_release_oid_set(minor_status, mechanisms); + *minor_status = 0; + return (GSS_S_NO_CRED); + } + + *minor_status = 0; + if (name_ret) + *name_ret = (gss_name_t) name; + if (lifetime) + *lifetime = min_lifetime; + if (cred && cred_usage) + *cred_usage = cred->gc_usage; + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c new file mode 100644 index 0000000000..771a6956a5 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c @@ -0,0 +1,79 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_inquire_cred_by_mech.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_inquire_cred_by_mech.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_inquire_cred_by_mech(OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t *cred_name, + OM_uint32 *initiator_lifetime, + OM_uint32 *acceptor_lifetime, + gss_cred_usage_t *cred_usage) +{ + OM_uint32 major_status; + gssapi_mech_interface m; + struct _gss_mechanism_cred *mcp; + gss_cred_id_t mc; + gss_name_t mn; + struct _gss_name *name; + + *minor_status = 0; + + m = __gss_get_mechanism(mech_type); + if (!m) + return (GSS_S_NO_CRED); + + if (cred_handle != GSS_C_NO_CREDENTIAL) { + struct _gss_cred *cred = (struct _gss_cred *) cred_handle; + SLIST_FOREACH(mcp, &cred->gc_mc, gmc_link) + if (mcp->gmc_mech == m) + break; + if (!mcp) + return (GSS_S_NO_CRED); + mc = mcp->gmc_cred; + } else { + mc = GSS_C_NO_CREDENTIAL; + } + + major_status = m->gm_inquire_cred_by_mech(minor_status, mc, mech_type, + &mn, initiator_lifetime, acceptor_lifetime, cred_usage); + if (major_status != GSS_S_COMPLETE) + return (major_status); + + name = _gss_make_name(m, mn); + if (!name) { + m->gm_release_name(minor_status, &mn); + return (GSS_S_NO_CRED); + } + + *cred_name = (gss_name_t) name; + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_oid.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_oid.c new file mode 100644 index 0000000000..3cfe89af21 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_oid.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +RCSID("$Id: gss_inquire_cred_by_oid.c,v 1.2 2006/06/28 16:20:41 lha Exp $"); + +OM_uint32 +gss_inquire_cred_by_oid (OM_uint32 *minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + struct _gss_cred *cred = (struct _gss_cred *) cred_handle; + OM_uint32 status = GSS_S_COMPLETE; + struct _gss_mechanism_cred *mc; + gssapi_mech_interface m; + gss_buffer_set_t set = GSS_C_NO_BUFFER_SET; + + *minor_status = 0; + + if (cred == NULL) + return GSS_S_NO_CRED; + + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { + gss_buffer_set_t rset = GSS_C_NO_BUFFER_SET; + int i; + + m = mc->gmc_mech; + if (m == NULL) + return GSS_S_BAD_MECH; + + if (m->gm_inquire_cred_by_oid == NULL) + continue; + + status = m->gm_inquire_cred_by_oid(minor_status, + mc->gmc_cred, desired_object, &rset); + if (status != GSS_S_COMPLETE) + continue; + + for (i = 0; i < rset->count; i++) { + status = gss_add_buffer_set_member(minor_status, + &rset->elements[i], &set); + if (status != GSS_S_COMPLETE) + break; + } + gss_release_buffer_set(minor_status, &rset); + } + if (set == GSS_C_NO_BUFFER_SET) + status = GSS_S_FAILURE; + *data_set = set; + return status; +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_mechs_for_name.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_mechs_for_name.c new file mode 100644 index 0000000000..7052bf8b72 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_mechs_for_name.c @@ -0,0 +1,77 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_inquire_mechs_for_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_inquire_mechs_for_name.c,v 1.3 2006/07/20 02:04:00 lha Exp $"); + +OM_uint32 +gss_inquire_mechs_for_name(OM_uint32 *minor_status, + const gss_name_t input_name, + gss_OID_set *mech_types) +{ + OM_uint32 major_status; + struct _gss_name *name = (struct _gss_name *) input_name; + struct _gss_mech_switch *m; + gss_OID_set name_types; + int present; + + *minor_status = 0; + + _gss_load_mech(); + + major_status = gss_create_empty_oid_set(minor_status, mech_types); + if (major_status) + return (major_status); + + /* + * We go through all the loaded mechanisms and see if this + * name's type is supported by the mechanism. If it is, add + * the mechanism to the set. + */ + SLIST_FOREACH(m, &_gss_mechs, gm_link) { + major_status = gss_inquire_names_for_mech(minor_status, + &m->gm_mech_oid, &name_types); + if (major_status) { + gss_release_oid_set(minor_status, mech_types); + return (major_status); + } + gss_test_oid_set_member(minor_status, + &name->gn_type, name_types, &present); + gss_release_oid_set(minor_status, &name_types); + if (present) { + major_status = gss_add_oid_set_member(minor_status, + &m->gm_mech_oid, mech_types); + if (major_status) { + gss_release_oid_set(minor_status, mech_types); + return (major_status); + } + } + } + + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_names_for_mech.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_names_for_mech.c new file mode 100644 index 0000000000..2293163b03 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_names_for_mech.c @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_inquire_names_for_mech.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_inquire_names_for_mech.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_inquire_names_for_mech(OM_uint32 *minor_status, + const gss_OID mechanism, + gss_OID_set *name_types) +{ + OM_uint32 major_status; + gssapi_mech_interface m = __gss_get_mechanism(mechanism); + + *minor_status = 0; + if (!m) + return (GSS_S_BAD_MECH); + + /* + * If the implementation can do it, ask it for a list of + * names, otherwise fake it. + */ + if (m->gm_inquire_names_for_mech) { + return (m->gm_inquire_names_for_mech(minor_status, + mechanism, name_types)); + } else { + major_status = gss_create_empty_oid_set(minor_status, + name_types); + if (major_status) + return (major_status); + major_status = gss_add_oid_set_member(minor_status, + GSS_C_NT_HOSTBASED_SERVICE, name_types); + if (major_status) { + OM_uint32 ms; + gss_release_oid_set(&ms, name_types); + return (major_status); + } + major_status = gss_add_oid_set_member(minor_status, + GSS_C_NT_USER_NAME, name_types); + if (major_status) { + OM_uint32 ms; + gss_release_oid_set(&ms, name_types); + return (major_status); + } + } + + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_inquire_sec_context_by_oid.c b/source4/heimdal/lib/gssapi/mech/gss_inquire_sec_context_by_oid.c new file mode 100644 index 0000000000..7f5632ac55 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_inquire_sec_context_by_oid.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +RCSID("$Id: gss_inquire_sec_context_by_oid.c,v 1.1 2006/06/28 09:07:08 lha Exp $"); + +OM_uint32 +gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + OM_uint32 major_status; + gssapi_mech_interface m; + + *minor_status = 0; + + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + + /* + * select the approprate underlying mechanism routine and + * call it. + */ + + m = ctx->gc_mech; + + if (m == NULL) + return GSS_S_BAD_MECH; + + if (m->gm_inquire_sec_context_by_oid != NULL) + major_status = m->gm_inquire_sec_context_by_oid(minor_status, + ctx->gc_ctx, desired_object, data_set); + else + major_status = GSS_S_BAD_MECH; + + return major_status; +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_krb5.c b/source4/heimdal/lib/gssapi/mech/gss_krb5.c new file mode 100644 index 0000000000..c6ea3cecb7 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_krb5.c @@ -0,0 +1,710 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_krb5.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +#include "krb5/gsskrb5_locl.h" +RCSID("$Id: gss_krb5.c,v 1.13 2006/10/20 22:05:02 lha Exp $"); + +#include <krb5.h> +#include <roken.h> + + +OM_uint32 +gss_krb5_copy_ccache(OM_uint32 *minor_status, + gss_cred_id_t cred, + krb5_ccache out) +{ + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + krb5_context context; + krb5_error_code kret; + krb5_ccache id; + OM_uint32 ret; + char *str; + + ret = gss_inquire_cred_by_oid(minor_status, + cred, + GSS_KRB5_COPY_CCACHE_X, + &data_set); + if (ret) + return ret; + + if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + kret = krb5_init_context(&context); + if (kret) { + *minor_status = kret; + gss_release_buffer_set(minor_status, &data_set); + return GSS_S_FAILURE; + } + + kret = asprintf(&str, "%.*s", (int)data_set->elements[0].length, + (char *)data_set->elements[0].value); + gss_release_buffer_set(minor_status, &data_set); + if (kret == -1) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + kret = krb5_cc_resolve(context, str, &id); + free(str); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + kret = krb5_cc_copy_cache(context, id, out); + krb5_cc_close(context, id); + krb5_free_context(context); + if (kret) { + *minor_status = kret; + return GSS_S_FAILURE; + } + + return ret; +} + +OM_uint32 +gss_krb5_import_cred(OM_uint32 *minor_status, + krb5_ccache id, + krb5_principal keytab_principal, + krb5_keytab keytab, + gss_cred_id_t *cred) +{ + gss_buffer_desc buffer; + OM_uint32 major_status; + krb5_context context; + krb5_error_code ret; + krb5_storage *sp; + krb5_data data; + char *str; + + *cred = GSS_C_NO_CREDENTIAL; + + ret = krb5_init_context(&context); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + sp = krb5_storage_emem(); + if (sp == NULL) { + *minor_status = ENOMEM; + major_status = GSS_S_FAILURE; + goto out; + } + + if (id) { + ret = krb5_cc_get_full_name(context, id, &str); + if (ret == 0) { + ret = krb5_store_string(sp, str); + free(str); + } + } else + ret = krb5_store_string(sp, ""); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto out; + } + + if (keytab_principal) { + ret = krb5_unparse_name(context, keytab_principal, &str); + if (ret == 0) { + ret = krb5_store_string(sp, str); + free(str); + } + } else + krb5_store_string(sp, ""); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto out; + } + + + if (keytab) { + ret = krb5_kt_get_full_name(context, keytab, &str); + if (ret == 0) { + ret = krb5_store_string(sp, str); + free(str); + } + } else + krb5_store_string(sp, ""); + if (ret) { + *minor_status = ret; + major_status = GSS_S_FAILURE; + goto out; + } + + krb5_storage_to_data(sp, &data); + + buffer.value = data.data; + buffer.length = data.length; + + major_status = gss_set_cred_option(minor_status, + cred, + GSS_KRB5_IMPORT_CRED_X, + &buffer); + krb5_data_free(&data); +out: + if (sp) + krb5_storage_free(sp); + krb5_free_context(context); + return major_status; +} + +OM_uint32 +gsskrb5_register_acceptor_identity(const char *identity) +{ + struct _gss_mech_switch *m; + gss_buffer_desc buffer; + OM_uint32 junk; + + _gss_load_mech(); + + buffer.value = rk_UNCONST(identity); + buffer.length = strlen(identity); + + SLIST_FOREACH(m, &_gss_mechs, gm_link) { + if (m->gm_mech.gm_set_sec_context_option == NULL) + continue; + m->gm_mech.gm_set_sec_context_option(&junk, NULL, + GSS_KRB5_REGISTER_ACCEPTOR_IDENTITY_X, &buffer); + } + + return (GSS_S_COMPLETE); +} + +OM_uint32 +gsskrb5_set_dns_canonicalize(int flag) +{ + struct _gss_mech_switch *m; + gss_buffer_desc buffer; + OM_uint32 junk; + char b = (flag != 0); + + _gss_load_mech(); + + buffer.value = &b; + buffer.length = sizeof(b); + + SLIST_FOREACH(m, &_gss_mechs, gm_link) { + if (m->gm_mech.gm_set_sec_context_option == NULL) + continue; + m->gm_mech.gm_set_sec_context_option(&junk, NULL, + GSS_KRB5_SET_DNS_CANONICALIZE_X, &buffer); + } + + return (GSS_S_COMPLETE); +} + + + +static krb5_error_code +set_key(krb5_keyblock *keyblock, gss_krb5_lucid_key_t *key) +{ + key->type = keyblock->keytype; + key->length = keyblock->keyvalue.length; + key->data = malloc(key->length); + if (key->data == NULL && key->length != 0) + return ENOMEM; + memcpy(key->data, keyblock->keyvalue.data, key->length); + return 0; +} + +static void +free_key(gss_krb5_lucid_key_t *key) +{ + memset(key->data, 0, key->length); + free(key->data); + memset(key, 0, sizeof(*key)); +} + + +OM_uint32 +gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + OM_uint32 version, + void **rctx) +{ + krb5_context context = NULL; + krb5_error_code ret; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + OM_uint32 major_status; + gss_krb5_lucid_context_v1_t *ctx = NULL; + krb5_storage *sp = NULL; + uint32_t num; + + if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT || version != 1) { + ret = EINVAL; + return GSS_S_FAILURE; + } + + major_status = + gss_inquire_sec_context_by_oid (minor_status, + *context_handle, + GSS_KRB5_EXPORT_LUCID_CONTEXT_V1_X, + &data_set); + if (major_status) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ret = krb5_init_context(&context); + if (ret) + goto out; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + ret = ENOMEM; + goto out; + } + + sp = krb5_storage_from_mem(data_set->elements[0].value, + data_set->elements[0].length); + if (sp == NULL) { + ret = ENOMEM; + goto out; + } + + ret = krb5_ret_uint32(sp, &num); + if (ret) goto out; + if (num != 1) { + ret = EINVAL; + goto out; + } + ctx->version = 1; + /* initiator */ + ret = krb5_ret_uint32(sp, &ctx->initiate); + if (ret) goto out; + /* endtime */ + ret = krb5_ret_uint32(sp, &ctx->endtime); + if (ret) goto out; + /* send_seq */ + ret = krb5_ret_uint32(sp, &num); + if (ret) goto out; + ctx->send_seq = ((uint64_t)num) << 32; + ret = krb5_ret_uint32(sp, &num); + if (ret) goto out; + ctx->send_seq |= num; + /* recv_seq */ + ret = krb5_ret_uint32(sp, &num); + if (ret) goto out; + ctx->recv_seq = ((uint64_t)num) << 32; + ret = krb5_ret_uint32(sp, &num); + if (ret) goto out; + ctx->recv_seq |= num; + /* protocol */ + ret = krb5_ret_uint32(sp, &ctx->protocol); + if (ret) goto out; + if (ctx->protocol == 0) { + krb5_keyblock key; + + /* sign_alg */ + ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.sign_alg); + if (ret) goto out; + /* seal_alg */ + ret = krb5_ret_uint32(sp, &ctx->rfc1964_kd.seal_alg); + if (ret) goto out; + /* ctx_key */ + ret = krb5_ret_keyblock(sp, &key); + if (ret) goto out; + ret = set_key(&key, &ctx->rfc1964_kd.ctx_key); + krb5_free_keyblock_contents(context, &key); + if (ret) goto out; + } else if (ctx->protocol == 1) { + krb5_keyblock key; + + /* acceptor_subkey */ + ret = krb5_ret_uint32(sp, &ctx->cfx_kd.have_acceptor_subkey); + if (ret) goto out; + /* ctx_key */ + ret = krb5_ret_keyblock(sp, &key); + if (ret) goto out; + ret = set_key(&key, &ctx->cfx_kd.ctx_key); + krb5_free_keyblock_contents(context, &key); + if (ret) goto out; + /* acceptor_subkey */ + if (ctx->cfx_kd.have_acceptor_subkey) { + ret = krb5_ret_keyblock(sp, &key); + if (ret) goto out; + ret = set_key(&key, &ctx->cfx_kd.acceptor_subkey); + krb5_free_keyblock_contents(context, &key); + if (ret) goto out; + } + } else { + ret = EINVAL; + goto out; + } + + *rctx = ctx; + +out: + gss_release_buffer_set(minor_status, &data_set); + if (sp) + krb5_storage_free(sp); + if (context) + krb5_free_context(context); + + if (ret) { + if (ctx) + gss_krb5_free_lucid_sec_context(NULL, ctx); + + *minor_status = ret; + return GSS_S_FAILURE; + } + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +gss_krb5_free_lucid_sec_context(OM_uint32 *minor_status, void *c) +{ + gss_krb5_lucid_context_v1_t *ctx = c; + + if (ctx->version != 1) { + if (minor_status) + *minor_status = 0; + return GSS_S_FAILURE; + } + + if (ctx->protocol == 0) { + free_key(&ctx->rfc1964_kd.ctx_key); + } else if (ctx->protocol == 1) { + free_key(&ctx->cfx_kd.ctx_key); + if (ctx->cfx_kd.have_acceptor_subkey) + free_key(&ctx->cfx_kd.acceptor_subkey); + } + free(ctx); + if (minor_status) + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +gsskrb5_set_send_to_kdc(struct gsskrb5_send_to_kdc *c) +{ + struct _gss_mech_switch *m; + gss_buffer_desc buffer; + OM_uint32 junk; + + _gss_load_mech(); + + if (c) { + buffer.value = c; + buffer.length = sizeof(*c); + } else { + buffer.value = NULL; + buffer.length = 0; + } + + SLIST_FOREACH(m, &_gss_mechs, gm_link) { + if (m->gm_mech.gm_set_sec_context_option == NULL) + continue; + m->gm_mech.gm_set_sec_context_option(&junk, NULL, + GSS_KRB5_SEND_TO_KDC_X, &buffer); + } + + return (GSS_S_COMPLETE); +} + +OM_uint32 +gsskrb5_extract_authtime_from_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + time_t *authtime) +{ + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + OM_uint32 maj_stat; + krb5_error_code ret; + OM_uint32 time32; + + if (context_handle == GSS_C_NO_CONTEXT) { + _gsskrb5_set_status("no context handle"); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + maj_stat = + gss_inquire_sec_context_by_oid (minor_status, + context_handle, + GSS_KRB5_GET_AUTHTIME_X, + &data_set); + if (maj_stat) + return maj_stat; + + if (data_set == GSS_C_NO_BUFFER_SET) { + _gsskrb5_set_status("no buffers returned"); + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (data_set->count != 1) { + _gsskrb5_set_status("%d != 1 buffers returned", data_set->count); + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (data_set->elements[0].length != 4) { + gss_release_buffer_set(minor_status, &data_set); + _gsskrb5_set_status("Error extracting authtime from security context: only got %d < 4 bytes", + data_set->elements[0].length); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ret = _gsskrb5_decode_om_uint32(data_set->elements[0].value, &time32); + if (ret) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = ret; + return GSS_S_FAILURE; + } + *authtime = time32; + + gss_release_buffer_set(minor_status, &data_set); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int ad_type, + gss_buffer_t ad_data) +{ + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + OM_uint32 maj_stat; + gss_OID_desc authz_oid_flat; + heim_oid authz_oid; + heim_oid new_authz_oid; + size_t size; + + if (context_handle == GSS_C_NO_CONTEXT) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + /* All this to append an integer to an oid... */ + + if (der_get_oid(GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->elements, + GSS_KRB5_EXTRACT_AUTHZ_DATA_FROM_SEC_CONTEXT_X->length, + &authz_oid, NULL) != 0) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + new_authz_oid.length = authz_oid.length + 1; + new_authz_oid.components = malloc(new_authz_oid.length * sizeof(*new_authz_oid.components)); + if (!new_authz_oid.components) { + free(authz_oid.components); + + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + memcpy(new_authz_oid.components, authz_oid.components, + authz_oid.length * sizeof(*authz_oid.components)); + + free(authz_oid.components); + + new_authz_oid.components[new_authz_oid.length - 1] = ad_type; + + authz_oid_flat.length = der_length_oid(&new_authz_oid); + authz_oid_flat.elements = malloc(authz_oid_flat.length); + + if (!authz_oid_flat.elements) { + free(new_authz_oid.components); + + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + if (der_put_oid((unsigned char *)authz_oid_flat.elements + authz_oid_flat.length - 1, + authz_oid_flat.length, + &new_authz_oid, &size) != 0) { + free(new_authz_oid.components); + + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + free(new_authz_oid.components); + + /* FINALLY, we have the OID */ + + maj_stat = + gss_inquire_sec_context_by_oid (minor_status, + context_handle, + &authz_oid_flat, + &data_set); + + free(authz_oid_flat.elements); + + if (maj_stat) + return maj_stat; + + if (data_set == GSS_C_NO_BUFFER_SET || data_set->count != 1) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + ad_data->value = malloc(data_set->elements[0].length); + if (ad_data->value == NULL) { + gss_release_buffer_set(minor_status, &data_set); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ad_data->length = data_set->elements[0].length; + memcpy(ad_data->value, data_set->elements[0].value, ad_data->length); + gss_release_buffer_set(minor_status, &data_set); + + *minor_status = 0; + return GSS_S_COMPLETE; +} + +static OM_uint32 +gsskrb5_extract_key(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + const gss_OID oid, + krb5_keyblock **keyblock) +{ + krb5_error_code ret; + gss_buffer_set_t data_set = GSS_C_NO_BUFFER_SET; + OM_uint32 major_status; + krb5_storage *sp = NULL; + + ret = _gsskrb5_init(); + if(ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (context_handle == GSS_C_NO_CONTEXT) { + _gsskrb5_set_status("no context handle"); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + major_status = + gss_inquire_sec_context_by_oid (minor_status, + context_handle, + oid, + &data_set); + if (major_status) + return major_status; + + if (data_set == GSS_C_NO_BUFFER_SET) { + _gsskrb5_set_status("no buffers returned"); + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + if (data_set->count != 1) { + _gsskrb5_set_status("%d != 1 buffers returned", data_set->count); + gss_release_buffer_set(minor_status, &data_set); + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + sp = krb5_storage_from_mem(data_set->elements[0].value, + data_set->elements[0].length); + if (sp == NULL) { + ret = ENOMEM; + goto out; + } + + *keyblock = calloc(1, sizeof(**keyblock)); + if (keyblock == NULL) { + ret = ENOMEM; + goto out; + } + + ret = krb5_ret_keyblock(sp, *keyblock); + +out: + gss_release_buffer_set(minor_status, &data_set); + if (sp) + krb5_storage_free(sp); + if (ret) { + _gsskrb5_set_error_string(); + if (keyblock) { + krb5_free_keyblock(_gsskrb5_context, *keyblock); + } + + *minor_status = ret; + return GSS_S_FAILURE; + } + *minor_status = 0; + return GSS_S_COMPLETE; +} + +OM_uint32 +gsskrb5_extract_service_keyblock(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + krb5_keyblock **keyblock) +{ + return gsskrb5_extract_key(minor_status, + context_handle, + GSS_KRB5_GET_SERVICE_KEYBLOCK_X, + keyblock); +} + +OM_uint32 +gsskrb5_get_initiator_subkey(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + krb5_keyblock **keyblock) +{ + return gsskrb5_extract_key(minor_status, + context_handle, + GSS_KRB5_GET_INITIATOR_SUBKEY_X, + keyblock); +} + +OM_uint32 +gsskrb5_get_subkey(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + krb5_keyblock **keyblock) +{ + return gsskrb5_extract_key(minor_status, + context_handle, + GSS_KRB5_GET_ACCEPTOR_SUBKEY_X, + keyblock); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c b/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c new file mode 100644 index 0000000000..3d01ba69d4 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c @@ -0,0 +1,324 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_mech_switch.c,v 1.2 2006/02/04 09:40:21 dfr Exp $ + */ + +#include "mech_locl.h" +#include <heim_threads.h> +RCSID("$Id: gss_mech_switch.c,v 1.7 2006/10/09 11:13:30 lha Exp $"); + +#ifndef _PATH_GSS_MECH +#define _PATH_GSS_MECH "/etc/gss/mech" +#endif + +struct _gss_mech_switch_list _gss_mechs = { NULL } ; +gss_OID_set _gss_mech_oids; +static HEIMDAL_MUTEX _gss_mech_mutex = HEIMDAL_MUTEX_INITIALIZER; + +/* + * Convert a string containing an OID in 'dot' form + * (e.g. 1.2.840.113554.1.2.2) to a gss_OID. + */ +static int +_gss_string_to_oid(const char* s, gss_OID oid) +{ + int number_count, i, j; + int byte_count; + const char *p, *q; + char *res; + + /* + * First figure out how many numbers in the oid, then + * calculate the compiled oid size. + */ + number_count = 0; + for (p = s; p; p = q) { + q = strchr(p, '.'); + if (q) q = q + 1; + number_count++; + } + + /* + * The first two numbers are in the first byte and each + * subsequent number is encoded in a variable byte sequence. + */ + if (number_count < 2) + return (EINVAL); + + /* + * We do this in two passes. The first pass, we just figure + * out the size. Second time around, we actually encode the + * number. + */ + res = 0; + for (i = 0; i < 2; i++) { + byte_count = 0; + for (p = s, j = 0; p; p = q, j++) { + unsigned int number = 0; + + /* + * Find the end of this number. + */ + q = strchr(p, '.'); + if (q) q = q + 1; + + /* + * Read the number of of the string. Don't + * bother with anything except base ten. + */ + while (*p && *p != '.') { + number = 10 * number + (*p - '0'); + p++; + } + + /* + * Encode the number. The first two numbers + * are packed into the first byte. Subsequent + * numbers are encoded in bytes seven bits at + * a time with the last byte having the high + * bit set. + */ + if (j == 0) { + if (res) + *res = number * 40; + } else if (j == 1) { + if (res) { + *res += number; + res++; + } + byte_count++; + } else if (j >= 2) { + /* + * The number is encoded in seven bit chunks. + */ + unsigned int t; + int bytes; + + bytes = 0; + for (t = number; t; t >>= 7) + bytes++; + if (bytes == 0) bytes = 1; + while (bytes) { + if (res) { + int bit = 7*(bytes-1); + + *res = (number >> bit) & 0x7f; + if (bytes != 1) + *res |= 0x80; + res++; + } + byte_count++; + bytes--; + } + } + } + if (!res) { + res = malloc(byte_count); + if (!res) + return (ENOMEM); + oid->length = byte_count; + oid->elements = res; + } + } + + return (0); +} + +#define SYM(name) \ +do { \ + m->gm_mech.gm_ ## name = dlsym(so, "gss_" #name); \ + if (!m->gm_mech.gm_ ## name) { \ + fprintf(stderr, "can't find symbol gss_" #name "\n"); \ + goto bad; \ + } \ +} while (0) + +#define OPTSYM(name) \ +do { \ + m->gm_mech.gm_ ## name = dlsym(so, "gss_" #name); \ +} while (0) + +/* + * + */ +static int +add_builtin(gssapi_mech_interface mech) +{ + struct _gss_mech_switch *m; + OM_uint32 minor_status; + + m = malloc(sizeof(*m)); + if (m == NULL) + return 1; + m->gm_so = NULL; + m->gm_mech = *mech; + m->gm_mech_oid = mech->gm_mech_oid; /* XXX */ + gss_add_oid_set_member(&minor_status, + &m->gm_mech.gm_mech_oid, &_gss_mech_oids); + + SLIST_INSERT_HEAD(&_gss_mechs, m, gm_link); + return 0; +} + +/* + * Load the mechanisms file (/etc/gss/mech). + */ +void +_gss_load_mech(void) +{ + OM_uint32 major_status, minor_status; + FILE *fp; + char buf[256]; + char *p; + char *name, *oid, *lib, *kobj; + struct _gss_mech_switch *m; + void *so; + + + HEIMDAL_MUTEX_lock(&_gss_mech_mutex); + + if (SLIST_FIRST(&_gss_mechs)) { + HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); + return; + } + + major_status = gss_create_empty_oid_set(&minor_status, + &_gss_mech_oids); + if (major_status) { + HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); + return; + } + + add_builtin(__gss_krb5_initialize()); + add_builtin(__gss_spnego_initialize()); + + fp = fopen(_PATH_GSS_MECH, "r"); + if (!fp) { +/* perror(_PATH_GSS_MECH); */ + HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); + return; + } + + while (fgets(buf, sizeof(buf), fp)) { + if (*buf == '#') + continue; + p = buf; + name = strsep(&p, "\t\n "); + if (p) while (isspace((unsigned char)*p)) p++; + oid = strsep(&p, "\t\n "); + if (p) while (isspace((unsigned char)*p)) p++; + lib = strsep(&p, "\t\n "); + if (p) while (isspace((unsigned char)*p)) p++; + kobj = strsep(&p, "\t\n "); + if (!name || !oid || !lib || !kobj) + continue; + +#ifndef RTLD_LOCAL +#define RTLD_LOCAL 0 +#endif + + so = dlopen(lib, RTLD_LOCAL); + if (!so) { +/* fprintf(stderr, "dlopen: %s\n", dlerror()); */ + continue; + } + + m = malloc(sizeof(*m)); + if (!m) + break; + m->gm_so = so; + if (_gss_string_to_oid(oid, &m->gm_mech.gm_mech_oid)) { + free(m); + continue; + } + + major_status = gss_add_oid_set_member(&minor_status, + &m->gm_mech.gm_mech_oid, &_gss_mech_oids); + if (major_status) { + free(m->gm_mech.gm_mech_oid.elements); + free(m); + continue; + } + + SYM(acquire_cred); + SYM(release_cred); + SYM(init_sec_context); + SYM(accept_sec_context); + SYM(process_context_token); + SYM(delete_sec_context); + SYM(context_time); + SYM(get_mic); + SYM(verify_mic); + SYM(wrap); + SYM(unwrap); + SYM(display_status); + SYM(indicate_mechs); + SYM(compare_name); + SYM(display_name); + SYM(import_name); + SYM(export_name); + SYM(release_name); + SYM(inquire_cred); + SYM(inquire_context); + SYM(wrap_size_limit); + SYM(add_cred); + SYM(inquire_cred_by_mech); + SYM(export_sec_context); + SYM(import_sec_context); + SYM(inquire_names_for_mech); + SYM(inquire_mechs_for_name); + SYM(canonicalize_name); + SYM(duplicate_name); + OPTSYM(inquire_cred_by_oid); + OPTSYM(inquire_sec_context_by_oid); + OPTSYM(set_sec_context_option); + OPTSYM(set_cred_option); + + SLIST_INSERT_HEAD(&_gss_mechs, m, gm_link); + continue; + + bad: + free(m->gm_mech.gm_mech_oid.elements); + free(m); + dlclose(so); + continue; + } + fclose(fp); + HEIMDAL_MUTEX_unlock(&_gss_mech_mutex); +} + +gssapi_mech_interface +__gss_get_mechanism(gss_OID mech) +{ + struct _gss_mech_switch *m; + + _gss_load_mech(); + SLIST_FOREACH(m, &_gss_mechs, gm_link) { + if (gss_oid_equal(&m->gm_mech.gm_mech_oid, mech)) + return &m->gm_mech; + } + return NULL; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_names.c b/source4/heimdal/lib/gssapi/mech/gss_names.c new file mode 100644 index 0000000000..833c582006 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_names.c @@ -0,0 +1,105 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_names.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_names.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +struct _gss_mechanism_name * +_gss_find_mn(struct _gss_name *name, gss_OID mech) +{ + OM_uint32 major_status, minor_status; + gssapi_mech_interface m; + struct _gss_mechanism_name *mn; + + SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { + if (gss_oid_equal(mech, mn->gmn_mech_oid)) + break; + } + + if (!mn) { + /* + * If this name is canonical (i.e. there is only an + * MN but it is from a different mech), give up now. + */ + if (!name->gn_value.value) + return (0); + + m = __gss_get_mechanism(mech); + if (!m) + return (0); + + mn = malloc(sizeof(struct _gss_mechanism_name)); + if (!mn) + return (0); + + major_status = m->gm_import_name(&minor_status, + &name->gn_value, + (name->gn_type.elements + ? &name->gn_type : GSS_C_NO_OID), + &mn->gmn_name); + if (major_status) { + free(mn); + return (0); + } + + mn->gmn_mech = m; + mn->gmn_mech_oid = &m->gm_mech_oid; + SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); + } + return (mn); +} + +/* + * Make a name from an MN. + */ +struct _gss_name * +_gss_make_name(gssapi_mech_interface m, gss_name_t new_mn) +{ + struct _gss_name *name; + struct _gss_mechanism_name *mn; + + name = malloc(sizeof(struct _gss_name)); + if (!name) + return (0); + memset(name, 0, sizeof(struct _gss_name)); + + mn = malloc(sizeof(struct _gss_mechanism_name)); + if (!mn) { + free(name); + return (0); + } + + SLIST_INIT(&name->gn_mn); + mn->gmn_mech = m; + mn->gmn_mech_oid = &m->gm_mech_oid; + mn->gmn_name = new_mn; + SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link); + + return (name); +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_oid_equal.c b/source4/heimdal/lib/gssapi/mech/gss_oid_equal.c new file mode 100644 index 0000000000..1a8b811f37 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_oid_equal.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +RCSID("$Id: gss_oid_equal.c,v 1.1 2006/06/28 09:07:08 lha Exp $"); + +int +gss_oid_equal(const gss_OID a, const gss_OID b) +{ + if (a == b) + return 1; + if (a == GSS_C_NO_OID || b == GSS_C_NO_OID || a->length != b->length) + return 0; + return memcmp(a->elements, b->elements, a->length) == 0; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_process_context_token.c b/source4/heimdal/lib/gssapi/mech/gss_process_context_token.c new file mode 100644 index 0000000000..1e6f39979f --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_process_context_token.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_process_context_token.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_process_context_token.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_process_context_token(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m = ctx->gc_mech; + + return (m->gm_process_context_token(minor_status, ctx->gc_ctx, + token_buffer)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_buffer.c b/source4/heimdal/lib/gssapi/mech/gss_release_buffer.c new file mode 100644 index 0000000000..66705bb40e --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_release_buffer.c @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_release_buffer.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_release_buffer.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_release_buffer(OM_uint32 *minor_status, + gss_buffer_t buffer) +{ + + *minor_status = 0; + if (buffer->value) + free(buffer->value); + buffer->length = 0; + buffer->value = 0; + + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_cred.c b/source4/heimdal/lib/gssapi/mech/gss_release_cred.c new file mode 100644 index 0000000000..760621c861 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_release_cred.c @@ -0,0 +1,52 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_release_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_release_cred.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) +{ + struct _gss_cred *cred = (struct _gss_cred *) *cred_handle; + struct _gss_mechanism_cred *mc; + + if (*cred_handle == GSS_C_NO_CREDENTIAL) + return (GSS_S_COMPLETE); + + while (SLIST_FIRST(&cred->gc_mc)) { + mc = SLIST_FIRST(&cred->gc_mc); + SLIST_REMOVE_HEAD(&cred->gc_mc, gmc_link); + mc->gmc_mech->gm_release_cred(minor_status, &mc->gmc_cred); + free(mc); + } + free(cred); + + *minor_status = 0; + *cred_handle = 0; + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_name.c b/source4/heimdal/lib/gssapi/mech/gss_release_name.c new file mode 100644 index 0000000000..1286cd3b79 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_release_name.c @@ -0,0 +1,55 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_release_name.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_release_name.c,v 1.3 2006/10/22 07:59:06 lha Exp $"); + +OM_uint32 +gss_release_name(OM_uint32 *minor_status, + gss_name_t *input_name) +{ + struct _gss_name *name = (struct _gss_name *) *input_name; + + *minor_status = 0; + if (name) { + if (name->gn_type.elements) + free(name->gn_type.elements); + while (SLIST_FIRST(&name->gn_mn)) { + struct _gss_mechanism_name *mn; + mn = SLIST_FIRST(&name->gn_mn); + SLIST_REMOVE_HEAD(&name->gn_mn, gmn_link); + mn->gmn_mech->gm_release_name(minor_status, + &mn->gmn_name); + free(mn); + } + gss_release_buffer(minor_status, &name->gn_value); + free(name); + *input_name = GSS_C_NO_NAME; + } + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_oid.c b/source4/heimdal/lib/gssapi/mech/gss_release_oid.c new file mode 100644 index 0000000000..fc84fabd29 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_release_oid.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +RCSID("$Id: gss_release_oid.c,v 1.1 2006/06/30 09:34:54 lha Exp $"); + +OM_uint32 +gss_release_oid(OM_uint32 *minor_status, gss_OID *oid) +{ + gss_OID o = *oid; + + *oid = GSS_C_NO_OID; + + if (minor_status != NULL) + *minor_status = 0; + + if (o == GSS_C_NO_OID) + return GSS_S_COMPLETE; + + if (o->elements != NULL) { + free(o->elements); + o->elements = NULL; + } + o->length = 0; + free(o); + + return GSS_S_COMPLETE; +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_oid_set.c b/source4/heimdal/lib/gssapi/mech/gss_release_oid_set.c new file mode 100644 index 0000000000..101657e4fb --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_release_oid_set.c @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_release_oid_set.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_release_oid_set.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_release_oid_set(OM_uint32 *minor_status, + gss_OID_set *set) +{ + + *minor_status = 0; + if (*set) { + if ((*set)->elements) + free((*set)->elements); + free(*set); + *set = 0; + } + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_seal.c b/source4/heimdal/lib/gssapi/mech/gss_seal.c new file mode 100644 index 0000000000..2f66f90d4f --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_seal.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_seal.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_seal.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_seal(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + int qop_req, + gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + + return (gss_wrap(minor_status, + context_handle, conf_req_flag, qop_req, + input_message_buffer, conf_state, + output_message_buffer)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c b/source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c new file mode 100644 index 0000000000..f8e013da18 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +RCSID("$Id: gss_set_cred_option.c,v 1.7 2006/07/01 08:50:49 lha Exp $"); + +OM_uint32 +gss_set_cred_option (OM_uint32 *minor_status, + gss_cred_id_t *cred_handle, + const gss_OID object, + const gss_buffer_t value) +{ + struct _gss_cred *cred = (struct _gss_cred *) *cred_handle; + OM_uint32 major_status = GSS_S_COMPLETE; + struct _gss_mechanism_cred *mc; + int one_ok = 0; + + *minor_status = 0; + + _gss_load_mech(); + + if (cred == NULL) { + struct _gss_mech_switch *m; + + cred = malloc(sizeof(*cred)); + if (cred == NULL) + return GSS_S_FAILURE; + + cred->gc_usage = GSS_C_BOTH; /* XXX */ + SLIST_INIT(&cred->gc_mc); + + SLIST_FOREACH(m, &_gss_mechs, gm_link) { + + if (m->gm_mech.gm_set_cred_option == NULL) + continue; + + mc = malloc(sizeof(*mc)); + if (mc == NULL) { + /* XXX free the other mc's */ + return GSS_S_FAILURE; + } + + mc->gmc_mech = &m->gm_mech; + mc->gmc_mech_oid = &m->gm_mech_oid; + mc->gmc_cred = GSS_C_NO_CREDENTIAL; + + major_status = m->gm_mech.gm_set_cred_option( + minor_status, &mc->gmc_cred, object, value); + + if (major_status) { + free(mc); + continue; + } + one_ok = 1; + SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); + } + *cred_handle = (gss_cred_id_t)cred; + if (!one_ok) { + OM_uint32 junk; + gss_release_cred(&junk, cred_handle); + } + } else { + gssapi_mech_interface m; + + SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { + m = mc->gmc_mech; + + if (m == NULL) + return GSS_S_BAD_MECH; + + if (m->gm_set_cred_option == NULL) + continue; + + major_status = m->gm_set_cred_option(minor_status, + &mc->gmc_cred, object, value); + if (major_status == GSS_S_BAD_MECH) + one_ok = 1; + } + } + if (one_ok) { + *minor_status = 0; + return GSS_S_COMPLETE; + } + return major_status; +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_set_sec_context_option.c b/source4/heimdal/lib/gssapi/mech/gss_set_sec_context_option.c new file mode 100644 index 0000000000..aa562a23b6 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_set_sec_context_option.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" +RCSID("$Id: gss_set_sec_context_option.c,v 1.2 2006/06/28 14:39:00 lha Exp $"); + +OM_uint32 +gss_set_sec_context_option (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + const gss_OID object, + const gss_buffer_t value) +{ + struct _gss_context *ctx; + OM_uint32 major_status; + gssapi_mech_interface m; + + *minor_status = 0; + + if (context_handle == NULL) + return GSS_S_NO_CONTEXT; + + ctx = (struct _gss_context *) *context_handle; + + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + + m = ctx->gc_mech; + + if (m == NULL) + return GSS_S_BAD_MECH; + + if (m->gm_set_sec_context_option != NULL) + major_status = m->gm_set_sec_context_option(minor_status, + &ctx->gc_ctx, object, value); + else + major_status = GSS_S_BAD_MECH; + + return major_status; +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_sign.c b/source4/heimdal/lib/gssapi/mech/gss_sign.c new file mode 100644 index 0000000000..8c854e5e43 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_sign.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_sign.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_sign.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_sign(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + int qop_req, + gss_buffer_t message_buffer, + gss_buffer_t message_token) +{ + + return gss_get_mic(minor_status, + context_handle, qop_req, message_buffer, message_token); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_test_oid_set_member.c b/source4/heimdal/lib/gssapi/mech/gss_test_oid_set_member.c new file mode 100644 index 0000000000..a71a8b7c92 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_test_oid_set_member.c @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_test_oid_set_member.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_test_oid_set_member.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_test_oid_set_member(OM_uint32 *minor_status, + const gss_OID member, + const gss_OID_set set, + int *present) +{ + int i; + + *present = 0; + for (i = 0; i < set->count; i++) + if (gss_oid_equal(member, &set->elements[i])) + *present = 1; + + *minor_status = 0; + return (GSS_S_COMPLETE); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_unseal.c b/source4/heimdal/lib/gssapi/mech/gss_unseal.c new file mode 100644 index 0000000000..128dc7883c --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_unseal.c @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_unseal.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_unseal.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_unseal(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + int *qop_state) +{ + + return (gss_unwrap(minor_status, + context_handle, input_message_buffer, + output_message_buffer, conf_state, (gss_qop_t *)qop_state)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_unwrap.c b/source4/heimdal/lib/gssapi/mech/gss_unwrap.c new file mode 100644 index 0000000000..1c9484b18d --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_unwrap.c @@ -0,0 +1,46 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_unwrap.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_unwrap.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_unwrap(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int *conf_state, + gss_qop_t *qop_state) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m = ctx->gc_mech; + + return (m->gm_unwrap(minor_status, ctx->gc_ctx, + input_message_buffer, output_message_buffer, + conf_state, qop_state)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_utils.c b/source4/heimdal/lib/gssapi/mech/gss_utils.c new file mode 100644 index 0000000000..33ee033209 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_utils.c @@ -0,0 +1,66 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_utils.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_utils.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +_gss_copy_oid(OM_uint32 *minor_status, + const gss_OID from_oid, gss_OID to_oid) +{ + size_t len = from_oid->length; + + *minor_status = 0; + to_oid->elements = malloc(len); + if (!to_oid->elements) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + to_oid->length = len; + memcpy(to_oid->elements, from_oid->elements, len); + return (GSS_S_COMPLETE); +} + + +OM_uint32 +_gss_copy_buffer(OM_uint32 *minor_status, + const gss_buffer_t from_buf, gss_buffer_t to_buf) +{ + size_t len = from_buf->length; + + *minor_status = 0; + to_buf->value = malloc(len); + if (!to_buf->value) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + to_buf->length = len; + memcpy(to_buf->value, from_buf->value, len); + return (GSS_S_COMPLETE); +} + diff --git a/source4/heimdal/lib/gssapi/mech/gss_verify.c b/source4/heimdal/lib/gssapi/mech/gss_verify.c new file mode 100644 index 0000000000..a99d17e2d7 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_verify.c @@ -0,0 +1,43 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_verify.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_verify.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_verify(OM_uint32 *minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t message_buffer, + gss_buffer_t token_buffer, + int *qop_state) +{ + + return (gss_verify_mic(minor_status, + context_handle, message_buffer, token_buffer, + (gss_qop_t *)qop_state)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_verify_mic.c b/source4/heimdal/lib/gssapi/mech/gss_verify_mic.c new file mode 100644 index 0000000000..b51ed7a8c4 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_verify_mic.c @@ -0,0 +1,44 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_verify_mic.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_verify_mic.c,v 1.2 2006/06/28 09:00:25 lha Exp $"); + +OM_uint32 +gss_verify_mic(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t *qop_state) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m = ctx->gc_mech; + + return (m->gm_verify_mic(minor_status, ctx->gc_ctx, + message_buffer, token_buffer, qop_state)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_wrap.c b/source4/heimdal/lib/gssapi/mech/gss_wrap.c new file mode 100644 index 0000000000..a97ec1308f --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_wrap.c @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_wrap.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_wrap.c,v 1.2 2006/06/28 09:00:26 lha Exp $"); + +OM_uint32 +gss_wrap(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int *conf_state, + gss_buffer_t output_message_buffer) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m = ctx->gc_mech; + + return (m->gm_wrap(minor_status, ctx->gc_ctx, + conf_req_flag, qop_req, input_message_buffer, + conf_state, output_message_buffer)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c b/source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c new file mode 100644 index 0000000000..27493aa90d --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c @@ -0,0 +1,45 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_wrap_size_limit.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" +RCSID("$Id: gss_wrap_size_limit.c,v 1.2 2006/06/28 09:00:26 lha Exp $"); + +OM_uint32 +gss_wrap_size_limit(OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 *max_input_size) +{ + struct _gss_context *ctx = (struct _gss_context *) context_handle; + gssapi_mech_interface m = ctx->gc_mech; + + return (m->gm_wrap_size_limit(minor_status, ctx->gc_ctx, + conf_req_flag, qop_req, req_output_size, max_input_size)); +} diff --git a/source4/heimdal/lib/gssapi/mech/gssapi.asn1 b/source4/heimdal/lib/gssapi/mech/gssapi.asn1 new file mode 100644 index 0000000000..544618b7d4 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/gssapi.asn1 @@ -0,0 +1,12 @@ +-- $Id: gssapi.asn1,v 1.3 2006/10/18 21:08:19 lha Exp $ + +GSS-API DEFINITIONS ::= BEGIN + +IMPORTS heim_any_set FROM heim; + +GSSAPIContextToken ::= [APPLICATION 0] IMPLICIT SEQUENCE { + thisMech OBJECT IDENTIFIER, + innerContextToken heim_any_set +} + +END
\ No newline at end of file diff --git a/source4/heimdal/lib/gssapi/mech/mech_locl.h b/source4/heimdal/lib/gssapi/mech/mech_locl.h new file mode 100644 index 0000000000..f5db15c5fa --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/mech_locl.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: mech_locl.h,v 1.4 2006/10/07 18:25:27 lha Exp $ */ + +#include <config.h> + +#include <krb5-types.h> + +#include <sys/types.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <dlfcn.h> +#include <errno.h> + +#include <gssapi_asn1.h> +#include <der.h> + +#include <roken.h> + +#include <gssapi.h> +#include <gssapi_mech.h> + +#include "mechqueue.h" + +#include "context.h" +#include "cred.h" +#include "mech_switch.h" +#include "name.h" +#include "utils.h" diff --git a/source4/heimdal/lib/gssapi/mech/mech_switch.h b/source4/heimdal/lib/gssapi/mech/mech_switch.h new file mode 100644 index 0000000000..0984d36ef3 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/mech_switch.h @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/mech_switch.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + * $Id: mech_switch.h,v 1.3 2006/10/05 18:31:53 lha Exp $ + */ + +#include <gssapi_mech.h> + +struct _gss_mech_switch { + SLIST_ENTRY(_gss_mech_switch) gm_link; + gss_OID_desc gm_mech_oid; + void *gm_so; + gssapi_mech_interface_desc gm_mech; +}; +SLIST_HEAD(_gss_mech_switch_list, _gss_mech_switch); +extern struct _gss_mech_switch_list _gss_mechs; +extern gss_OID_set _gss_mech_oids; + +void _gss_load_mech(void); diff --git a/source4/heimdal/lib/gssapi/mech/mechqueue.h b/source4/heimdal/lib/gssapi/mech/mechqueue.h new file mode 100644 index 0000000000..8434b76c00 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/mechqueue.h @@ -0,0 +1,101 @@ +/* $NetBSD: queue.h,v 1.39 2004/04/18 14:25:34 lukem Exp $ */ + +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + */ + +#ifndef _MECHQUEUE_H_ +#define _MECHQUEUE_H_ + +#ifndef SLIST_HEAD + +/* + * Singly-linked List definitions. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_INIT(head) do { \ + (head)->slh_first = NULL; \ +} while (/*CONSTCOND*/0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + (elm)->field.sle_next = (slistelm)->field.sle_next; \ + (slistelm)->field.sle_next = (elm); \ +} while (/*CONSTCOND*/0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + (elm)->field.sle_next = (head)->slh_first; \ + (head)->slh_first = (elm); \ +} while (/*CONSTCOND*/0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + (head)->slh_first = (head)->slh_first->field.sle_next; \ +} while (/*CONSTCOND*/0) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if ((head)->slh_first == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = (head)->slh_first; \ + while(curelm->field.sle_next != (elm)) \ + curelm = curelm->field.sle_next; \ + curelm->field.sle_next = \ + curelm->field.sle_next->field.sle_next; \ + } \ +} while (/*CONSTCOND*/0) + +#define SLIST_FOREACH(var, head, field) \ + for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) + +/* + * Singly-linked List access methods. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) +#define SLIST_FIRST(head) ((head)->slh_first) +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#endif /* SLIST_HEAD */ + +#endif /* !_MECHQUEUE_H_ */ diff --git a/source4/heimdal/lib/gssapi/mech/name.h b/source4/heimdal/lib/gssapi/mech/name.h new file mode 100644 index 0000000000..3e7443ba20 --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/name.h @@ -0,0 +1,47 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/name.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + * $Id: name.h,v 1.4 2006/10/05 18:36:07 lha Exp $ + */ + +struct _gss_mechanism_name { + SLIST_ENTRY(_gss_mechanism_name) gmn_link; + gssapi_mech_interface gmn_mech; /* mechanism ops for MN */ + gss_OID gmn_mech_oid; /* mechanism oid for MN */ + gss_name_t gmn_name; /* underlying MN */ +}; +SLIST_HEAD(_gss_mechanism_name_list, _gss_mechanism_name); + +struct _gss_name { + gss_OID_desc gn_type; /* type of name */ + gss_buffer_desc gn_value; /* value (as imported) */ + struct _gss_mechanism_name_list gn_mn; /* list of MNs */ +}; + +struct _gss_mechanism_name * + _gss_find_mn(struct _gss_name *name, gss_OID mech); +struct _gss_name * + _gss_make_name(gssapi_mech_interface m, gss_name_t new_mn); diff --git a/source4/heimdal/lib/gssapi/mech/utils.h b/source4/heimdal/lib/gssapi/mech/utils.h new file mode 100644 index 0000000000..75a507298c --- /dev/null +++ b/source4/heimdal/lib/gssapi/mech/utils.h @@ -0,0 +1,32 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/utils.h,v 1.1 2005/12/29 14:40:20 dfr Exp $ + * $Id: utils.h,v 1.3 2006/07/20 01:48:25 lha Exp $ + */ + +OM_uint32 _gss_copy_oid(OM_uint32 *, const gss_OID, gss_OID); +OM_uint32 _gss_copy_buffer(OM_uint32 *minor_status, + const gss_buffer_t from_buf, gss_buffer_t to_buf); diff --git a/source4/heimdal/lib/gssapi/spnego.asn1 b/source4/heimdal/lib/gssapi/spnego.asn1 deleted file mode 100755 index 5dc767cf76..0000000000 --- a/source4/heimdal/lib/gssapi/spnego.asn1 +++ /dev/null @@ -1,42 +0,0 @@ --- $Id: spnego.asn1,v 1.4 2004/03/07 13:38:08 lha Exp $ - -SPNEGO DEFINITIONS ::= -BEGIN - -MechType::= OBJECT IDENTIFIER - -MechTypeList ::= SEQUENCE OF MechType - -ContextFlags ::= BIT STRING { - delegFlag (0), - mutualFlag (1), - replayFlag (2), - sequenceFlag (3), - anonFlag (4), - confFlag (5), - integFlag (6) -} - -NegTokenInit ::= SEQUENCE { - mechTypes [0] MechTypeList OPTIONAL, - reqFlags [1] ContextFlags OPTIONAL, - mechToken [2] OCTET STRING OPTIONAL, - mechListMIC [3] OCTET STRING OPTIONAL - } - -NegTokenTarg ::= SEQUENCE { - negResult [0] ENUMERATED { - accept_completed (0), - accept_incomplete (1), - reject (2) } OPTIONAL, - supportedMech [1] MechType OPTIONAL, - responseToken [2] OCTET STRING OPTIONAL, - mechListMIC [3] OCTET STRING OPTIONAL -} - -NegotiationToken ::= CHOICE { - negTokenInit[0] NegTokenInit, - negTokenTarg[1] NegTokenTarg -} - -END diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c new file mode 100644 index 0000000000..8a885a3e2f --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c @@ -0,0 +1,873 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * Portions Copyright (c) 2004 PADL Software Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id: accept_sec_context.c,v 1.6 2006/10/07 22:26:57 lha Exp $"); + +OM_uint32 +_gss_spnego_encode_response(OM_uint32 *minor_status, + const NegTokenResp *resp, + gss_buffer_t data, + u_char **ret_buf) +{ + OM_uint32 ret; + u_char *buf; + size_t buf_size, buf_len; + + buf_size = 1024; + buf = malloc(buf_size); + if (buf == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + do { + ret = encode_NegTokenResp(buf + buf_size - 1, + buf_size, + resp, &buf_len); + if (ret == 0) { + size_t tmp; + + ret = der_put_length_and_tag(buf + buf_size - buf_len - 1, + buf_size - buf_len, + buf_len, + ASN1_C_CONTEXT, + CONS, + 1, + &tmp); + if (ret == 0) + buf_len += tmp; + } + if (ret) { + if (ret == ASN1_OVERFLOW) { + u_char *tmp; + + buf_size *= 2; + tmp = realloc (buf, buf_size); + if (tmp == NULL) { + *minor_status = ENOMEM; + free(buf); + return GSS_S_FAILURE; + } + buf = tmp; + } else { + *minor_status = ret; + free(buf); + return GSS_S_FAILURE; + } + } + } while (ret == ASN1_OVERFLOW); + + data->value = buf + buf_size - buf_len; + data->length = buf_len; + *ret_buf = buf; + + return GSS_S_COMPLETE; +} + +static OM_uint32 +send_reject (OM_uint32 *minor_status, + gss_buffer_t output_token) +{ + NegTokenResp resp; + gss_buffer_desc data; + u_char *buf; + OM_uint32 ret; + + ALLOC(resp.negResult, 1); + if (resp.negResult == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + *(resp.negResult) = reject; + resp.supportedMech = NULL; + resp.responseToken = NULL; + resp.mechListMIC = NULL; + + ret = _gss_spnego_encode_response (minor_status, &resp, &data, &buf); + free_NegTokenResp(&resp); + if (ret != GSS_S_COMPLETE) + return ret; + + output_token->value = malloc(data.length); + if (output_token->value == NULL) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + } else { + output_token->length = data.length; + memcpy(output_token->value, data.value, output_token->length); + } + free(buf); + if (ret != GSS_S_COMPLETE) + return ret; + return GSS_S_BAD_MECH; +} + +OM_uint32 +_gss_spnego_indicate_mechtypelist (OM_uint32 *minor_status, + int includeMSCompatOID, + const gssspnego_cred cred_handle, + MechTypeList *mechtypelist, + gss_OID *preferred_mech) +{ + OM_uint32 ret; + gss_OID_set supported_mechs = GSS_C_NO_OID_SET; + int i, count; + + if (cred_handle != NULL) { + ret = gss_inquire_cred(minor_status, + cred_handle->negotiated_cred_id, + NULL, + NULL, + NULL, + &supported_mechs); + } else { + ret = gss_indicate_mechs(minor_status, &supported_mechs); + } + + if (ret != GSS_S_COMPLETE) { + return ret; + } + + if (supported_mechs->count == 0) { + *minor_status = ENOENT; + gss_release_oid_set(minor_status, &supported_mechs); + return GSS_S_FAILURE; + } + + count = supported_mechs->count; + if (includeMSCompatOID) + count++; + + mechtypelist->len = 0; + mechtypelist->val = calloc(count, sizeof(MechType)); + if (mechtypelist->val == NULL) { + *minor_status = ENOMEM; + gss_release_oid_set(minor_status, &supported_mechs); + return GSS_S_FAILURE; + } + + for (i = 0; i < supported_mechs->count; i++) { + ret = _gss_spnego_add_mech_type(&supported_mechs->elements[i], + includeMSCompatOID, + mechtypelist); + if (ret != 0) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + break; + } + } + + if (ret == GSS_S_COMPLETE && preferred_mech != NULL) { + ret = gss_duplicate_oid(minor_status, + &supported_mechs->elements[0], + preferred_mech); + } + + if (ret != GSS_S_COMPLETE) { + free_MechTypeList(mechtypelist); + mechtypelist->len = 0; + mechtypelist->val = NULL; + } + gss_release_oid_set(minor_status, &supported_mechs); + + return ret; +} + +static OM_uint32 +send_supported_mechs (OM_uint32 *minor_status, + gss_buffer_t output_token) +{ + NegTokenInit ni; + char hostname[MAXHOSTNAMELEN], *p; + gss_buffer_desc name_buf; + gss_OID name_type; + gss_name_t target_princ; + gss_name_t canon_princ; + OM_uint32 ret, minor; + u_char *buf; + size_t buf_size, buf_len; + gss_buffer_desc data; + + memset(&ni, 0, sizeof(ni)); + + ni.reqFlags = NULL; + ni.mechToken = NULL; + ni.negHints = NULL; + ni.mechListMIC = NULL; + + ret = _gss_spnego_indicate_mechtypelist(minor_status, 1, + NULL, + &ni.mechTypes, NULL); + if (ret != GSS_S_COMPLETE) { + return ret; + } + + memset(&target_princ, 0, sizeof(target_princ)); + if (gethostname(hostname, sizeof(hostname) - 1) != 0) { + *minor_status = errno; + free_NegTokenInit(&ni); + return GSS_S_FAILURE; + } + + /* Send the constructed SAM name for this host */ + for (p = hostname; *p != '\0' && *p != '.'; p++) { + *p = toupper((unsigned char)*p); + } + *p++ = '$'; + *p = '\0'; + + name_buf.length = strlen(hostname); + name_buf.value = hostname; + + ret = gss_import_name(minor_status, &name_buf, + GSS_C_NO_OID, + &target_princ); + if (ret != GSS_S_COMPLETE) { + return ret; + } + + name_buf.length = 0; + name_buf.value = NULL; + + /* Canonicalize the name using the preferred mechanism */ + ret = gss_canonicalize_name(minor_status, + target_princ, + GSS_C_NO_OID, + &canon_princ); + if (ret != GSS_S_COMPLETE) { + gss_release_name(&minor, &target_princ); + return ret; + } + + ret = gss_display_name(minor_status, canon_princ, + &name_buf, &name_type); + if (ret != GSS_S_COMPLETE) { + gss_release_name(&minor, &canon_princ); + gss_release_name(&minor, &target_princ); + return ret; + } + + gss_release_name(&minor, &canon_princ); + gss_release_name(&minor, &target_princ); + + ALLOC(ni.negHints, 1); + if (ni.negHints == NULL) { + *minor_status = ENOMEM; + gss_release_buffer(&minor, &name_buf); + free_NegTokenInit(&ni); + return GSS_S_FAILURE; + } + + ALLOC(ni.negHints->hintName, 1); + if (ni.negHints->hintName == NULL) { + *minor_status = ENOMEM; + gss_release_buffer(&minor, &name_buf); + free_NegTokenInit(&ni); + return GSS_S_FAILURE; + } + + *(ni.negHints->hintName) = name_buf.value; + name_buf.value = NULL; + ni.negHints->hintAddress = NULL; + + buf_size = 1024; + buf = malloc(buf_size); + if (buf == NULL) { + free_NegTokenInit(&ni); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + do { + ret = encode_NegTokenInit(buf + buf_size - 1, + buf_size, + &ni, &buf_len); + if (ret == 0) { + size_t tmp; + + ret = der_put_length_and_tag(buf + buf_size - buf_len - 1, + buf_size - buf_len, + buf_len, + ASN1_C_CONTEXT, + CONS, + 0, + &tmp); + if (ret == 0) + buf_len += tmp; + } + if (ret) { + if (ret == ASN1_OVERFLOW) { + u_char *tmp; + + buf_size *= 2; + tmp = realloc (buf, buf_size); + if (tmp == NULL) { + *minor_status = ENOMEM; + free(buf); + free_NegTokenInit(&ni); + return GSS_S_FAILURE; + } + buf = tmp; + } else { + *minor_status = ret; + free(buf); + free_NegTokenInit(&ni); + return GSS_S_FAILURE; + } + } + } while (ret == ASN1_OVERFLOW); + + data.value = buf + buf_size - buf_len; + data.length = buf_len; + + ret = gss_encapsulate_token(&data, + GSS_SPNEGO_MECHANISM, + output_token); + free (buf); + free_NegTokenInit (&ni); + + if (ret != GSS_S_COMPLETE) + return ret; + + *minor_status = 0; + + return GSS_S_CONTINUE_NEEDED; +} + +static OM_uint32 +send_accept (OM_uint32 *minor_status, + gssspnego_ctx context_handle, + gss_buffer_t mech_token, + int initial_response, + gss_buffer_t mech_buf, + gss_buffer_t output_token) +{ + NegTokenResp resp; + gss_buffer_desc data; + u_char *buf; + OM_uint32 ret; + gss_buffer_desc mech_mic_buf; + + memset(&resp, 0, sizeof(resp)); + + ALLOC(resp.negResult, 1); + if (resp.negResult == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + if (context_handle->open) { + if (mech_token != GSS_C_NO_BUFFER + && mech_token->length != 0 + && mech_buf != GSS_C_NO_BUFFER) + *(resp.negResult) = accept_incomplete; + else + *(resp.negResult) = accept_completed; + } else { + if (initial_response && context_handle->require_mic) + *(resp.negResult) = request_mic; + else + *(resp.negResult) = accept_incomplete; + } + + if (initial_response) { + ALLOC(resp.supportedMech, 1); + if (resp.supportedMech == NULL) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ret = der_get_oid(context_handle->preferred_mech_type->elements, + context_handle->preferred_mech_type->length, + resp.supportedMech, + NULL); + if (ret) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + } else { + resp.supportedMech = NULL; + } + + if (mech_token != GSS_C_NO_BUFFER && mech_token->length != 0) { + ALLOC(resp.responseToken, 1); + if (resp.responseToken == NULL) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + resp.responseToken->length = mech_token->length; + resp.responseToken->data = mech_token->value; + mech_token->length = 0; + mech_token->value = NULL; + } else { + resp.responseToken = NULL; + } + + if (mech_buf != GSS_C_NO_BUFFER) { + ALLOC(resp.mechListMIC, 1); + if (resp.mechListMIC == NULL) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ret = gss_get_mic(minor_status, + context_handle->negotiated_ctx_id, + 0, + mech_buf, + &mech_mic_buf); + if (ret != GSS_S_COMPLETE) { + free_NegTokenResp(&resp); + return ret; + } + + resp.mechListMIC->length = mech_mic_buf.length; + resp.mechListMIC->data = mech_mic_buf.value; + } else + resp.mechListMIC = NULL; + + ret = _gss_spnego_encode_response (minor_status, &resp, &data, &buf); + if (ret != GSS_S_COMPLETE) { + free_NegTokenResp(&resp); + return ret; + } + + /* + * The response should not be encapsulated, because + * it is a SubsequentContextToken (note though RFC 1964 + * specifies encapsulation for all _Kerberos_ tokens). + */ + output_token->value = malloc(data.length); + if (output_token->value == NULL) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + } else { + output_token->length = data.length; + memcpy(output_token->value, data.value, output_token->length); + } + free(buf); + if (ret != GSS_S_COMPLETE) { + free_NegTokenResp(&resp); + return ret; + } + + ret = (*(resp.negResult) == accept_completed) ? GSS_S_COMPLETE : + GSS_S_CONTINUE_NEEDED; + free_NegTokenResp(&resp); + return ret; +} + + +static OM_uint32 +verify_mechlist_mic + (OM_uint32 *minor_status, + gssspnego_ctx context_handle, + gss_buffer_t mech_buf, + heim_octet_string *mechListMIC + ) +{ + OM_uint32 ret; + gss_buffer_desc mic_buf; + + if (context_handle->verified_mic) { + /* This doesn't make sense, we've already verified it? */ + *minor_status = 0; + return GSS_S_DUPLICATE_TOKEN; + } + + if (mechListMIC == NULL) { + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + + mic_buf.length = mechListMIC->length; + mic_buf.value = mechListMIC->data; + + ret = gss_verify_mic(minor_status, + context_handle->negotiated_ctx_id, + mech_buf, + &mic_buf, + NULL); + + if (ret != GSS_S_COMPLETE) + ret = GSS_S_DEFECTIVE_TOKEN; + + return ret; +} + +OM_uint32 +_gss_spnego_accept_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t *delegated_cred_handle + ) +{ + OM_uint32 ret, ret2, minor; + NegTokenInit ni; + NegTokenResp na; + size_t ni_len, na_len; + int i; + gss_buffer_desc data; + size_t len, taglen; + int initialToken; + unsigned int negResult = accept_incomplete; + gss_buffer_t mech_input_token = GSS_C_NO_BUFFER; + gss_buffer_t mech_output_token = GSS_C_NO_BUFFER; + gss_buffer_desc mech_buf; + gss_OID preferred_mech_type = GSS_C_NO_OID; + gssspnego_ctx ctx; + gssspnego_cred acceptor_cred = (gssspnego_cred)acceptor_cred_handle; + + *minor_status = 0; + + output_token->length = 0; + output_token->value = NULL; + + if (src_name != NULL) + *src_name = GSS_C_NO_NAME; + + if (mech_type != NULL) + *mech_type = GSS_C_NO_OID; + + if (ret_flags != NULL) + *ret_flags = 0; + + if (time_rec != NULL) + *time_rec = 0; + + if (delegated_cred_handle != NULL) + *delegated_cred_handle = GSS_C_NO_CREDENTIAL; + + mech_buf.value = NULL; + + if (*context_handle == GSS_C_NO_CONTEXT) { + ret = _gss_spnego_alloc_sec_context(minor_status, + context_handle); + if (ret != GSS_S_COMPLETE) + return ret; + + if (input_token_buffer->length == 0) { + return send_supported_mechs (minor_status, + output_token); + } + } + + ctx = (gssspnego_ctx)*context_handle; + + /* + * The GSS-API encapsulation is only present on the initial + * context token (negTokenInit). + */ + ret = gss_decapsulate_token (input_token_buffer, + GSS_SPNEGO_MECHANISM, + &data); + initialToken = (ret == GSS_S_COMPLETE); + + if (!initialToken) { + data.value = input_token_buffer->value; + data.length = input_token_buffer->length; + } + + ret = der_match_tag_and_length(data.value, data.length, + ASN1_C_CONTEXT, CONS, + initialToken ? 0 : 1, + &len, &taglen); + if (ret) { + *minor_status = ret; + return GSS_S_FAILURE; + } + + if (len > data.length - taglen) { + *minor_status = ASN1_OVERRUN; + return GSS_S_FAILURE; + } + + if (initialToken) { + ret = decode_NegTokenInit((const unsigned char *)data.value + taglen, + len, &ni, &ni_len); + } else { + ret = decode_NegTokenResp((const unsigned char *)data.value + taglen, + len, &na, &na_len); + } + if (ret) { + *minor_status = ret; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (!initialToken && na.negResult != NULL) { + negResult = *(na.negResult); + } + + if (negResult == reject || negResult == request_mic) { + /* request_mic should only be sent by acceptor */ + free_NegTokenResp(&na); + return GSS_S_DEFECTIVE_TOKEN; + } + + if (initialToken) { + for (i = 0; i < ni.mechTypes.len; ++i) { + /* Call glue layer to find first mech we support */ + ret = _gss_spnego_select_mech(minor_status, &ni.mechTypes.val[i], + &preferred_mech_type); + if (ret == 0) + break; + } + if (preferred_mech_type == GSS_C_NO_OID) { + free_NegTokenInit(&ni); + return GSS_S_BAD_MECH; + } + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (initialToken) { + ctx->preferred_mech_type = preferred_mech_type; + ctx->initiator_mech_types.len = ni.mechTypes.len; + ctx->initiator_mech_types.val = ni.mechTypes.val; + ni.mechTypes.len = 0; + ni.mechTypes.val = NULL; + } + + { + gss_buffer_desc ibuf, obuf; + int require_mic, verify_mic, get_mic; + int require_response; + heim_octet_string *mic; + + if (initialToken) { + if (ni.mechToken != NULL) { + ibuf.length = ni.mechToken->length; + ibuf.value = ni.mechToken->data; + mech_input_token = &ibuf; + } + } else { + if (na.responseToken != NULL) { + ibuf.length = na.responseToken->length; + ibuf.value = na.responseToken->data; + mech_input_token = &ibuf; + } + } + + if (mech_input_token != GSS_C_NO_BUFFER) { + gss_cred_id_t mech_cred; + gss_cred_id_t mech_delegated_cred; + gss_cred_id_t *mech_delegated_cred_p; + + if (acceptor_cred != NULL) + mech_cred = acceptor_cred->negotiated_cred_id; + else + mech_cred = GSS_C_NO_CREDENTIAL; + + if (delegated_cred_handle != NULL) { + mech_delegated_cred = GSS_C_NO_CREDENTIAL; + mech_delegated_cred_p = &mech_delegated_cred; + } else { + mech_delegated_cred_p = NULL; + } + + if (ctx->mech_src_name != GSS_C_NO_NAME) + gss_release_name(&minor, &ctx->mech_src_name); + + if (ctx->delegated_cred_id != GSS_C_NO_CREDENTIAL) + _gss_spnego_release_cred(&minor, &ctx->delegated_cred_id); + + ret = gss_accept_sec_context(&minor, + &ctx->negotiated_ctx_id, + mech_cred, + mech_input_token, + input_chan_bindings, + &ctx->mech_src_name, + &ctx->negotiated_mech_type, + &obuf, + &ctx->mech_flags, + &ctx->mech_time_rec, + mech_delegated_cred_p); + if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { + if (mech_delegated_cred_p != NULL && + mech_delegated_cred != GSS_C_NO_CREDENTIAL) { + ret2 = _gss_spnego_alloc_cred(minor_status, + mech_delegated_cred, + &ctx->delegated_cred_id); + if (ret2 != GSS_S_COMPLETE) + ret = ret2; + } + mech_output_token = &obuf; + } + if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) { + if (initialToken) + free_NegTokenInit(&ni); + else + free_NegTokenResp(&na); + send_reject (minor_status, output_token); + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + if (ret == GSS_S_COMPLETE) + ctx->open = 1; + } else + ret = GSS_S_COMPLETE; + + ret2 = _gss_spnego_require_mechlist_mic(minor_status, + ctx, + &require_mic); + if (ret2) + goto out; + + ctx->require_mic = require_mic; + + mic = initialToken ? ni.mechListMIC : na.mechListMIC; + if (mic != NULL) + require_mic = 1; + + if (ctx->open && require_mic) { + if (mech_input_token == GSS_C_NO_BUFFER) { /* Even/One */ + verify_mic = 1; + get_mic = 0; + } else if (mech_output_token != GSS_C_NO_BUFFER && + mech_output_token->length == 0) { /* Odd */ + get_mic = verify_mic = 1; + } else { /* Even/One */ + verify_mic = 0; + get_mic = 1; + } + + if (verify_mic || get_mic) { + int eret; + size_t buf_len; + + ASN1_MALLOC_ENCODE(MechTypeList, + mech_buf.value, mech_buf.length, + &ctx->initiator_mech_types, &buf_len, eret); + if (eret) { + ret2 = GSS_S_FAILURE; + *minor_status = eret; + goto out; + } + if (mech_buf.length != buf_len) + abort(); + } + + if (verify_mic) { + ret2 = verify_mechlist_mic(minor_status, ctx, &mech_buf, mic); + if (ret2) { + if (get_mic) + send_reject (minor_status, output_token); + goto out; + } + + ctx->verified_mic = 1; + } + } else + verify_mic = get_mic = 0; + + if (ctx->mech_flags & GSS_C_DCE_STYLE) + require_response = (negResult != accept_completed); + else + require_response = 0; + + /* + * Check whether we need to send a result: there should be only + * one accept_completed response sent in the entire negotiation + */ + if ((mech_output_token != GSS_C_NO_BUFFER && + mech_output_token->length != 0) + || require_response + || get_mic) { + ret2 = send_accept (minor_status, + ctx, + mech_output_token, + initialToken, + get_mic ? &mech_buf : NULL, + output_token); + if (ret2) + goto out; + } + + out: + if (ret2 != GSS_S_COMPLETE) + ret = ret2; + if (mech_output_token != NULL) + gss_release_buffer(&minor, mech_output_token); + if (mech_buf.value != NULL) + free(mech_buf.value); + if (initialToken) + free_NegTokenInit(&ni); + else + free_NegTokenResp(&na); + } + + if (ret == GSS_S_COMPLETE) { + if (src_name != NULL) { + ret2 = gss_duplicate_name(minor_status, + ctx->mech_src_name, + src_name); + if (ret2 != GSS_S_COMPLETE) + ret = ret2; + } + if (delegated_cred_handle != NULL) { + *delegated_cred_handle = ctx->delegated_cred_id; + ctx->delegated_cred_id = GSS_C_NO_CREDENTIAL; + } + } + + if (mech_type != NULL) + *mech_type = ctx->negotiated_mech_type; + if (ret_flags != NULL) + *ret_flags = ctx->mech_flags; + if (time_rec != NULL) + *time_rec = ctx->mech_time_rec; + + if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + + _gss_spnego_internal_delete_sec_context(&minor, context_handle, + GSS_C_NO_BUFFER); + + return ret; +} + diff --git a/source4/heimdal/lib/gssapi/spnego/compat.c b/source4/heimdal/lib/gssapi/spnego/compat.c new file mode 100644 index 0000000000..aeae088258 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/compat.c @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id: compat.c,v 1.6 2006/10/07 22:26:59 lha Exp $"); + +/* + * Apparently Microsoft got the OID wrong, and used + * 1.2.840.48018.1.2.2 instead. We need both this and + * the correct Kerberos OID here in order to deal with + * this. Because this is manifest in SPNEGO only I'd + * prefer to deal with this here rather than inside the + * Kerberos mechanism. + */ +static gss_OID_desc gss_mskrb_mechanism_oid_desc = + {9, (void *)"\x2a\x86\x48\x82\xf7\x12\x01\x02\x02"}; + +static gss_OID_desc gss_krb5_mechanism_oid_desc = + {9, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02"}; + +/* + * Allocate a SPNEGO context handle + */ +OM_uint32 _gss_spnego_alloc_sec_context (OM_uint32 * minor_status, + gss_ctx_id_t *context_handle) +{ + gssspnego_ctx ctx; + + ctx = calloc(1, sizeof(*ctx)); + if (ctx == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ctx->initiator_mech_types.len = 0; + ctx->initiator_mech_types.val = NULL; + ctx->preferred_mech_type = GSS_C_NO_OID; + ctx->negotiated_mech_type = GSS_C_NO_OID; + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + + /* + * Cache these so we can return them before returning + * GSS_S_COMPLETE, even if the mechanism has itself + * completed earlier + */ + ctx->mech_flags = 0; + ctx->mech_time_rec = 0; + ctx->mech_src_name = GSS_C_NO_NAME; + ctx->delegated_cred_id = GSS_C_NO_CREDENTIAL; + + ctx->open = 0; + ctx->local = 0; + ctx->require_mic = 0; + ctx->verified_mic = 0; + + HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex); + + *context_handle = (gss_ctx_id_t)ctx; + + return GSS_S_COMPLETE; +} + +/* + * Free a SPNEGO context handle. The caller must have acquired + * the lock before this is called. + */ +OM_uint32 _gss_spnego_internal_delete_sec_context + (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token + ) +{ + gssspnego_ctx ctx; + OM_uint32 ret, minor; + + *minor_status = 0; + + if (context_handle == NULL) { + return GSS_S_NO_CONTEXT; + } + + if (output_token != GSS_C_NO_BUFFER) { + output_token->length = 0; + output_token->value = NULL; + } + + ctx = (gssspnego_ctx)*context_handle; + *context_handle = GSS_C_NO_CONTEXT; + + if (ctx == NULL) { + return GSS_S_NO_CONTEXT; + } + + if (ctx->initiator_mech_types.val != NULL) + free_MechTypeList(&ctx->initiator_mech_types); + + _gss_spnego_release_cred(&minor, &ctx->delegated_cred_id); + + gss_release_oid(&minor, &ctx->preferred_mech_type); + ctx->negotiated_mech_type = GSS_C_NO_OID; + + gss_release_name(&minor, &ctx->mech_src_name); + + if (ctx->negotiated_ctx_id != GSS_C_NO_CONTEXT) { + ret = gss_delete_sec_context(minor_status, + &ctx->negotiated_ctx_id, + output_token); + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + } else { + ret = GSS_S_COMPLETE; + } + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex); + + free(ctx); + *context_handle = NULL; + + return ret; +} + +/* + * For compatability with the Windows SPNEGO implementation, the + * default is to ignore the mechListMIC unless CFX is used and + * a non-preferred mechanism was negotiated + */ + +OM_uint32 +_gss_spnego_require_mechlist_mic(OM_uint32 *minor_status, + gssspnego_ctx ctx, + int *require_mic) +{ + gss_buffer_set_t buffer_set = GSS_C_NO_BUFFER_SET; + OM_uint32 minor; + + *minor_status = 0; + *require_mic = 0; + + if (ctx == NULL) { + return GSS_S_COMPLETE; + } + + if (ctx->require_mic) { + /* Acceptor requested it: mandatory to honour */ + *require_mic = 1; + return GSS_S_COMPLETE; + } + + /* + * Check whether peer indicated implicit support for updated SPNEGO + * (eg. in the Kerberos case by using CFX) + */ + if (gss_inquire_sec_context_by_oid(&minor, ctx->negotiated_ctx_id, + GSS_C_PEER_HAS_UPDATED_SPNEGO, + &buffer_set) == GSS_S_COMPLETE) { + *require_mic = 1; + gss_release_buffer_set(&minor, &buffer_set); + } + + /* Safe-to-omit MIC rules follow */ + if (*require_mic) { + if (gss_oid_equal(ctx->negotiated_mech_type, ctx->preferred_mech_type)) { + *require_mic = 0; + } else if (gss_oid_equal(ctx->negotiated_mech_type, &gss_krb5_mechanism_oid_desc) && + gss_oid_equal(ctx->preferred_mech_type, &gss_mskrb_mechanism_oid_desc)) { + *require_mic = 0; + } + } + + return GSS_S_COMPLETE; +} + +int _gss_spnego_add_mech_type(gss_OID mech_type, + int includeMSCompatOID, + MechTypeList *mechtypelist) +{ + int ret; + + if (gss_oid_equal(mech_type, GSS_SPNEGO_MECHANISM)) + return 0; + + if (includeMSCompatOID && + gss_oid_equal(mech_type, &gss_krb5_mechanism_oid_desc)) { + ret = der_get_oid(gss_mskrb_mechanism_oid_desc.elements, + gss_mskrb_mechanism_oid_desc.length, + &mechtypelist->val[mechtypelist->len], + NULL); + if (ret) + return ret; + mechtypelist->len++; + } + ret = der_get_oid(mech_type->elements, + mech_type->length, + &mechtypelist->val[mechtypelist->len], + NULL); + if (ret) + return ret; + mechtypelist->len++; + + return 0; +} + +OM_uint32 +_gss_spnego_select_mech(OM_uint32 *minor_status, + MechType *mechType, + gss_OID *mech_p) +{ + char mechbuf[64]; + size_t mech_len; + gss_OID_desc oid; + OM_uint32 ret; + + ret = der_put_oid ((unsigned char *)mechbuf + sizeof(mechbuf) - 1, + sizeof(mechbuf), + mechType, + &mech_len); + if (ret) { + return GSS_S_DEFECTIVE_TOKEN; + } + + oid.length = mech_len; + oid.elements = mechbuf + sizeof(mechbuf) - mech_len; + + if (gss_oid_equal(&oid, GSS_SPNEGO_MECHANISM)) { + return GSS_S_BAD_MECH; + } + + *minor_status = 0; + + /* Translate broken MS Kebreros OID */ + if (gss_oid_equal(&oid, &gss_mskrb_mechanism_oid_desc)) { + gssapi_mech_interface mech; + + mech = __gss_get_mechanism(&gss_krb5_mechanism_oid_desc); + if (mech == NULL) + return GSS_S_BAD_MECH; + + ret = gss_duplicate_oid(minor_status, + &gss_mskrb_mechanism_oid_desc, + mech_p); + } else { + gssapi_mech_interface mech; + + mech = __gss_get_mechanism(&oid); + if (mech == NULL) + return GSS_S_BAD_MECH; + + ret = gss_duplicate_oid(minor_status, + &mech->gm_mech_oid, + mech_p); + } + + return ret; +} + diff --git a/source4/heimdal/lib/gssapi/spnego/context_stubs.c b/source4/heimdal/lib/gssapi/spnego/context_stubs.c new file mode 100644 index 0000000000..902ddbbdf9 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/context_stubs.c @@ -0,0 +1,835 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id: context_stubs.c,v 1.8 2006/10/07 22:27:01 lha Exp $"); + +static OM_uint32 +spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs) +{ + OM_uint32 ret, junk; + gss_OID_set m; + int i; + + ret = gss_indicate_mechs(minor_status, &m); + if (ret != GSS_S_COMPLETE) + return ret; + + ret = gss_create_empty_oid_set(minor_status, mechs); + if (ret != GSS_S_COMPLETE) { + gss_release_oid_set(&junk, &m); + return ret; + } + + for (i = 0; i < m->count; i++) { + if (gss_oid_equal(&m->elements[i], GSS_SPNEGO_MECHANISM)) + continue; + + ret = gss_add_oid_set_member(minor_status, &m->elements[i], mechs); + if (ret) { + gss_release_oid_set(&junk, &m); + gss_release_oid_set(&junk, mechs); + return ret; + } + } + return ret; +} + + + +OM_uint32 _gss_spnego_process_context_token + (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer + ) +{ + gss_ctx_id_t context ; + gssspnego_ctx ctx; + OM_uint32 ret; + + if (context_handle == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + context = context_handle; + ctx = (gssspnego_ctx)context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + ret = gss_process_context_token(minor_status, + ctx->negotiated_ctx_id, + token_buffer); + if (ret != GSS_S_COMPLETE) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; + } + + ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT; + + return _gss_spnego_internal_delete_sec_context(minor_status, + &context, + GSS_C_NO_BUFFER); +} + +OM_uint32 _gss_spnego_delete_sec_context + (OM_uint32 *minor_status, + gss_ctx_id_t *context_handle, + gss_buffer_t output_token + ) +{ + gssspnego_ctx ctx; + + if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) + return GSS_S_NO_CONTEXT; + + ctx = (gssspnego_ctx)*context_handle; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + return _gss_spnego_internal_delete_sec_context(minor_status, + context_handle, + output_token); +} + +OM_uint32 _gss_spnego_context_time + (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + OM_uint32 *time_rec + ) +{ + gssspnego_ctx ctx; + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_context_time(minor_status, + ctx->negotiated_ctx_id, + time_rec); +} + +OM_uint32 _gss_spnego_get_mic + (OM_uint32 *minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_get_mic(minor_status, ctx->negotiated_ctx_id, + qop_req, message_buffer, message_token); +} + +OM_uint32 _gss_spnego_verify_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_verify_mic(minor_status, + ctx->negotiated_ctx_id, + message_buffer, + token_buffer, + qop_state); +} + +OM_uint32 _gss_spnego_wrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_wrap(minor_status, + ctx->negotiated_ctx_id, + conf_req_flag, + qop_req, + input_message_buffer, + conf_state, + output_message_buffer); +} + +OM_uint32 _gss_spnego_unwrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_unwrap(minor_status, + ctx->negotiated_ctx_id, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state); +} + +OM_uint32 _gss_spnego_display_status + (OM_uint32 * minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 * message_context, + gss_buffer_t status_string + ) +{ + return GSS_S_FAILURE; +} + +OM_uint32 _gss_spnego_compare_name + (OM_uint32 *minor_status, + const gss_name_t name1, + const gss_name_t name2, + int * name_equal + ) +{ + return gss_compare_name(minor_status, name1, name2, name_equal); +} + +OM_uint32 _gss_spnego_display_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID * output_name_type + ) +{ + return gss_display_name(minor_status, input_name, + output_name_buffer, output_name_type); +} + +OM_uint32 _gss_spnego_import_name + (OM_uint32 * minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t * output_name + ) +{ + return gss_import_name(minor_status, input_name_buffer, + input_name_type, output_name); +} + +OM_uint32 _gss_spnego_export_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t exported_name + ) +{ + return gss_export_name(minor_status, input_name, + exported_name); +} + +OM_uint32 _gss_spnego_release_name + (OM_uint32 * minor_status, + gss_name_t * input_name + ) +{ + return gss_release_name(minor_status, input_name); +} + +OM_uint32 _gss_spnego_inquire_context ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open_context + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_inquire_context(minor_status, + ctx->negotiated_ctx_id, + src_name, + targ_name, + lifetime_rec, + mech_type, + ctx_flags, + locally_initiated, + open_context); +} + +OM_uint32 _gss_spnego_wrap_size_limit ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 * max_input_size + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_wrap_size_limit(minor_status, + ctx->negotiated_ctx_id, + conf_req_flag, + qop_req, + req_output_size, + max_input_size); +} + +OM_uint32 _gss_spnego_export_sec_context ( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t interprocess_token + ) +{ + gssspnego_ctx ctx; + OM_uint32 ret; + + *minor_status = 0; + + if (context_handle == NULL) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)*context_handle; + + if (ctx == NULL) + return GSS_S_NO_CONTEXT; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return GSS_S_NO_CONTEXT; + } + + ret = gss_export_sec_context(minor_status, + &ctx->negotiated_ctx_id, + interprocess_token); + if (ret == GSS_S_COMPLETE) { + ret = _gss_spnego_internal_delete_sec_context(minor_status, + context_handle, + GSS_C_NO_BUFFER); + if (ret == GSS_S_COMPLETE) + return GSS_S_COMPLETE; + } + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + return ret; +} + +OM_uint32 _gss_spnego_import_sec_context ( + OM_uint32 * minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t *context_handle + ) +{ + OM_uint32 ret, minor; + gss_ctx_id_t context; + gssspnego_ctx ctx; + + ret = _gss_spnego_alloc_sec_context(minor_status, &context); + if (ret != GSS_S_COMPLETE) { + return ret; + } + ctx = (gssspnego_ctx)context; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + ret = gss_import_sec_context(minor_status, + interprocess_token, + &ctx->negotiated_ctx_id); + if (ret != GSS_S_COMPLETE) { + _gss_spnego_internal_delete_sec_context(&minor, context_handle, GSS_C_NO_BUFFER); + return ret; + } + + ctx->open = 1; + /* don't bother filling in the rest of the fields */ + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + *context_handle = (gss_ctx_id_t)ctx; + + return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_inquire_names_for_mech ( + OM_uint32 * minor_status, + const gss_OID mechanism, + gss_OID_set * name_types + ) +{ + gss_OID_set mechs, names, n; + OM_uint32 ret, junk; + int i, j; + + *name_types = NULL; + + ret = spnego_supported_mechs(minor_status, &mechs); + if (ret != GSS_S_COMPLETE) + return ret; + + ret = gss_create_empty_oid_set(minor_status, &names); + if (ret != GSS_S_COMPLETE) + goto out; + + for (i = 0; i < mechs->count; i++) { + ret = gss_inquire_names_for_mech(minor_status, + &mechs->elements[i], + &n); + if (ret) + continue; + + for (j = 0; j < n->count; j++) + gss_add_oid_set_member(minor_status, + &n->elements[j], + &names); + gss_release_oid_set(&junk, &n); + } + + ret = GSS_S_COMPLETE; + *name_types = names; +out: + + gss_release_oid_set(&junk, &mechs); + + return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_inquire_mechs_for_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + gss_OID_set * mech_types + ) +{ + OM_uint32 ret, junk; + + ret = gss_create_empty_oid_set(minor_status, mech_types); + if (ret) + return ret; + + ret = gss_add_oid_set_member(minor_status, + GSS_SPNEGO_MECHANISM, + mech_types); + if (ret) + gss_release_oid_set(&junk, mech_types); + + return ret; +} + +OM_uint32 _gss_spnego_canonicalize_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + const gss_OID mech_type, + gss_name_t * output_name + ) +{ + /* XXX */ + return gss_duplicate_name(minor_status, input_name, output_name); +} + +OM_uint32 _gss_spnego_duplicate_name ( + OM_uint32 * minor_status, + const gss_name_t src_name, + gss_name_t * dest_name + ) +{ + return gss_duplicate_name(minor_status, src_name, dest_name); +} + +OM_uint32 _gss_spnego_sign + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int qop_req, + gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_sign(minor_status, + ctx->negotiated_ctx_id, + qop_req, + message_buffer, + message_token); +} + +OM_uint32 _gss_spnego_verify + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t message_buffer, + gss_buffer_t token_buffer, + int * qop_state + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_verify(minor_status, + ctx->negotiated_ctx_id, + message_buffer, + token_buffer, + qop_state); +} + +OM_uint32 _gss_spnego_seal + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + int qop_req, + gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_seal(minor_status, + ctx->negotiated_ctx_id, + conf_req_flag, + qop_req, + input_message_buffer, + conf_state, + output_message_buffer); +} + +OM_uint32 _gss_spnego_unseal + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + int * qop_state + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_unseal(minor_status, + ctx->negotiated_ctx_id, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state); +} + +#if 0 +OM_uint32 _gss_spnego_unwrap_ex + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_header_buffer, + const gss_buffer_t associated_data_buffer, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_unwrap_ex(minor_status, + ctx->negotiated_ctx_id, + token_header_buffer, + associated_data_buffer, + input_message_buffer, + output_message_buffer, + conf_state, + qop_state); +} + +OM_uint32 _gss_spnego_wrap_ex + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t associated_data_buffer, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_token_buffer, + gss_buffer_t output_message_buffer + ) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + if ((ctx->mech_flags & GSS_C_DCE_STYLE) == 0 && + associated_data_buffer->length != input_message_buffer->length) { + *minor_status = EINVAL; + return GSS_S_BAD_QOP; + } + + return gss_wrap_ex(minor_status, + ctx->negotiated_ctx_id, + conf_req_flag, + qop_req, + associated_data_buffer, + input_message_buffer, + conf_state, + output_token_buffer, + output_message_buffer); +} + +OM_uint32 _gss_spnego_complete_auth_token + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_complete_auth_token(minor_status, + ctx->negotiated_ctx_id, + input_message_buffer); +} +#endif + +OM_uint32 _gss_spnego_inquire_sec_context_by_oid + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_inquire_sec_context_by_oid(minor_status, + ctx->negotiated_ctx_id, + desired_object, + data_set); +} + +OM_uint32 _gss_spnego_set_sec_context_option + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_OID desired_object, + const gss_buffer_t value) +{ + gssspnego_ctx ctx; + + *minor_status = 0; + + if (context_handle == NULL || *context_handle == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + ctx = (gssspnego_ctx)context_handle; + + if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) { + return GSS_S_NO_CONTEXT; + } + + return gss_set_sec_context_option(minor_status, + &ctx->negotiated_ctx_id, + desired_object, + value); +} + diff --git a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c new file mode 100644 index 0000000000..8f8edab15e --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id: cred_stubs.c,v 1.5 2006/10/07 22:27:04 lha Exp $"); + +OM_uint32 +_gss_spnego_release_cred(OM_uint32 *minor_status, gss_cred_id_t *cred_handle) +{ + gssspnego_cred cred; + OM_uint32 ret; + + *minor_status = 0; + + if (*cred_handle == GSS_C_NO_CREDENTIAL) { + return GSS_S_COMPLETE; + } + cred = (gssspnego_cred)*cred_handle; + + ret = gss_release_cred(minor_status, &cred->negotiated_cred_id); + + free(cred); + *cred_handle = GSS_C_NO_CREDENTIAL; + + return ret; +} + +OM_uint32 +_gss_spnego_alloc_cred(OM_uint32 *minor_status, + gss_cred_id_t mech_cred_handle, + gss_cred_id_t *cred_handle) +{ + gssspnego_cred cred; + + if (*cred_handle != GSS_C_NO_CREDENTIAL) { + *minor_status = EINVAL; + return GSS_S_FAILURE; + } + + cred = calloc(1, sizeof(*cred)); + if (cred == NULL) { + *cred_handle = GSS_C_NO_CREDENTIAL; + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + cred->negotiated_cred_id = mech_cred_handle; + + *cred_handle = (gss_cred_id_t)cred; + + return GSS_S_COMPLETE; +} + +/* + * For now, just a simple wrapper that avoids recursion. When + * we support gss_{get,set}_neg_mechs() we will need to expose + * more functionality. + */ +OM_uint32 _gss_spnego_acquire_cred +(OM_uint32 *minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret, tmp; + gss_OID_set_desc actual_desired_mechs; + gss_OID_set mechs; + int i, j; + gss_cred_id_t cred_handle = GSS_C_NO_CREDENTIAL; + gssspnego_cred cred; + + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + ret = gss_indicate_mechs(minor_status, &mechs); + if (ret != GSS_S_COMPLETE) + return ret; + + /* Remove ourselves from this list */ + actual_desired_mechs.count = mechs->count; + actual_desired_mechs.elements = malloc(actual_desired_mechs.count * + sizeof(gss_OID_desc)); + if (actual_desired_mechs.elements == NULL) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + goto out; + } + + for (i = 0, j = 0; i < mechs->count; i++) { + if (gss_oid_equal(&mechs->elements[i], GSS_SPNEGO_MECHANISM)) + continue; + + actual_desired_mechs.elements[j] = mechs->elements[i]; + j++; + } + actual_desired_mechs.count = j; + + ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL, + &cred_handle); + if (ret != GSS_S_COMPLETE) + goto out; + + cred = (gssspnego_cred)cred_handle; + ret = gss_acquire_cred(minor_status, desired_name, + time_req, &actual_desired_mechs, + cred_usage, + &cred->negotiated_cred_id, + actual_mechs, time_rec); + if (ret != GSS_S_COMPLETE) + goto out; + + *output_cred_handle = cred_handle; + +out: + gss_release_oid_set(&tmp, &mechs); + if (actual_desired_mechs.elements != NULL) { + free(actual_desired_mechs.elements); + } + if (ret != GSS_S_COMPLETE) { + _gss_spnego_release_cred(&tmp, &cred_handle); + } + + return ret; +} + +OM_uint32 _gss_spnego_inquire_cred + (OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + gss_name_t * name, + OM_uint32 * lifetime, + gss_cred_usage_t * cred_usage, + gss_OID_set * mechanisms + ) +{ + gssspnego_cred cred; + OM_uint32 ret; + + if (cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + + cred = (gssspnego_cred)cred_handle; + + ret = gss_inquire_cred(minor_status, + cred->negotiated_cred_id, + name, + lifetime, + cred_usage, + mechanisms); + + return ret; +} + +OM_uint32 _gss_spnego_add_cred ( + OM_uint32 * minor_status, + const gss_cred_id_t input_cred_handle, + const gss_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * initiator_time_rec, + OM_uint32 * acceptor_time_rec + ) +{ + gss_cred_id_t spnego_output_cred_handle = GSS_C_NO_CREDENTIAL; + OM_uint32 ret, tmp; + gssspnego_cred input_cred, output_cred; + + *output_cred_handle = GSS_C_NO_CREDENTIAL; + + ret = _gss_spnego_alloc_cred(minor_status, GSS_C_NO_CREDENTIAL, + &spnego_output_cred_handle); + if (ret) + return ret; + + input_cred = (gssspnego_cred)input_cred_handle; + output_cred = (gssspnego_cred)spnego_output_cred_handle; + + ret = gss_add_cred(minor_status, + input_cred->negotiated_cred_id, + desired_name, + desired_mech, + cred_usage, + initiator_time_req, + acceptor_time_req, + &output_cred->negotiated_cred_id, + actual_mechs, + initiator_time_rec, + acceptor_time_rec); + if (ret) { + _gss_spnego_release_cred(&tmp, &spnego_output_cred_handle); + return ret; + } + + *output_cred_handle = spnego_output_cred_handle; + + return GSS_S_COMPLETE; +} + +OM_uint32 _gss_spnego_inquire_cred_by_mech ( + OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t * name, + OM_uint32 * initiator_lifetime, + OM_uint32 * acceptor_lifetime, + gss_cred_usage_t * cred_usage + ) +{ + gssspnego_cred cred; + OM_uint32 ret; + + if (cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + + cred = (gssspnego_cred)cred_handle; + + ret = gss_inquire_cred_by_mech(minor_status, + cred->negotiated_cred_id, + mech_type, + name, + initiator_lifetime, + acceptor_lifetime, + cred_usage); + + return ret; +} + +OM_uint32 _gss_spnego_inquire_cred_by_oid + (OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + const gss_OID desired_object, + gss_buffer_set_t *data_set) +{ + gssspnego_cred cred; + OM_uint32 ret; + + if (cred_handle == GSS_C_NO_CREDENTIAL) { + *minor_status = 0; + return GSS_S_NO_CRED; + } + cred = (gssspnego_cred)cred_handle; + + ret = gss_inquire_cred_by_oid(minor_status, + cred->negotiated_cred_id, + desired_object, + data_set); + + return ret; +} + diff --git a/source4/heimdal/lib/gssapi/spnego/external.c b/source4/heimdal/lib/gssapi/spnego/external.c new file mode 100644 index 0000000000..b7e02a55e1 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/external.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" +#include <gssapi_mech.h> + +RCSID("$Id: external.c,v 1.7 2006/10/07 22:27:06 lha Exp $"); + +/* + * RFC2478, SPNEGO: + * The security mechanism of the initial + * negotiation token is identified by the Object Identifier + * iso.org.dod.internet.security.mechanism.snego (1.3.6.1.5.5.2). + */ + +static gssapi_mech_interface_desc spnego_mech = { + GMI_VERSION, + "spnego", + {6, (void *)"\x2b\x06\x01\x05\x05\x02"}, + _gss_spnego_acquire_cred, + _gss_spnego_release_cred, + _gss_spnego_init_sec_context, + _gss_spnego_accept_sec_context, + _gss_spnego_process_context_token, + _gss_spnego_internal_delete_sec_context, + _gss_spnego_context_time, + _gss_spnego_get_mic, + _gss_spnego_verify_mic, + _gss_spnego_wrap, + _gss_spnego_unwrap, + _gss_spnego_display_status, + NULL, + _gss_spnego_compare_name, + _gss_spnego_display_name, + _gss_spnego_import_name, + _gss_spnego_export_name, + _gss_spnego_release_name, + _gss_spnego_inquire_cred, + _gss_spnego_inquire_context, + _gss_spnego_wrap_size_limit, + _gss_spnego_add_cred, + _gss_spnego_inquire_cred_by_mech, + _gss_spnego_export_sec_context, + _gss_spnego_import_sec_context, + _gss_spnego_inquire_names_for_mech, + _gss_spnego_inquire_mechs_for_name, + _gss_spnego_canonicalize_name, + _gss_spnego_duplicate_name +}; + +gssapi_mech_interface +__gss_spnego_initialize(void) +{ + return &spnego_mech; +} + +static gss_OID_desc _gss_spnego_mechanism_desc = + {6, (void *)"\x2b\x06\x01\x05\x05\x02"}; + +gss_OID GSS_SPNEGO_MECHANISM = &_gss_spnego_mechanism_desc; diff --git a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c new file mode 100644 index 0000000000..5a652fdb2e --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c @@ -0,0 +1,578 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * Portions Copyright (c) 2004 PADL Software Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "spnego/spnego_locl.h" + +RCSID("$Id: init_sec_context.c,v 1.6 2006/10/14 10:09:15 lha Exp $"); + +/* + * Send a reply. Note that we only need to send a reply if we + * need to send a MIC or a mechanism token. Otherwise, we can + * return an empty buffer. + * + * The return value of this will be returned to the API, so it + * must return GSS_S_CONTINUE_NEEDED if a token was generated. + */ +static OM_uint32 +spnego_reply_internal(OM_uint32 *minor_status, + gssspnego_ctx context_handle, + const gss_buffer_t mech_buf, + gss_buffer_t mech_token, + gss_buffer_t output_token) +{ + NegTokenResp resp; + gss_buffer_desc mic_buf; + OM_uint32 ret; + gss_buffer_desc data; + u_char *buf; + + if (mech_buf == GSS_C_NO_BUFFER && mech_token->length == 0) { + output_token->length = 0; + output_token->value = NULL; + + return context_handle->open ? GSS_S_COMPLETE : GSS_S_FAILURE; + } + + memset(&resp, 0, sizeof(resp)); + + ALLOC(resp.negResult, 1); + if (resp.negResult == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + resp.supportedMech = NULL; + + output_token->length = 0; + output_token->value = NULL; + + if (mech_token->length == 0) { + resp.responseToken = NULL; + *(resp.negResult) = accept_completed; + } else { + ALLOC(resp.responseToken, 1); + if (resp.responseToken == NULL) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + resp.responseToken->length = mech_token->length; + resp.responseToken->data = mech_token->value; + mech_token->length = 0; + mech_token->value = NULL; + + *(resp.negResult) = accept_incomplete; + } + + if (mech_buf != GSS_C_NO_BUFFER) { + ALLOC(resp.mechListMIC, 1); + if (resp.mechListMIC == NULL) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + ret = gss_get_mic(minor_status, + context_handle->negotiated_ctx_id, + 0, + mech_buf, + &mic_buf); + if (ret) { + free_NegTokenResp(&resp); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + resp.mechListMIC->length = mic_buf.length; + resp.mechListMIC->data = mic_buf.value; + } else { + resp.mechListMIC = NULL; + } + + ret = _gss_spnego_encode_response (minor_status, &resp, + &data, &buf); + if (ret) { + free_NegTokenResp(&resp); + return ret; + } + + output_token->value = malloc(data.length); + if (output_token->value == NULL) { + *minor_status = ENOMEM; + ret = GSS_S_FAILURE; + } else { + output_token->length = data.length; + memcpy(output_token->value, data.value, output_token->length); + } + free(buf); + + if (*(resp.negResult) == accept_completed) + ret = GSS_S_COMPLETE; + else + ret = GSS_S_CONTINUE_NEEDED; + + free_NegTokenResp(&resp); + return ret; +} + +static OM_uint32 +spnego_initial + (OM_uint32 * minor_status, + gssspnego_cred cred, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + NegTokenInit ni; + int ret; + OM_uint32 sub, minor; + gss_buffer_desc mech_token; + u_char *buf; + size_t buf_size, buf_len; + gss_buffer_desc data; + size_t ni_len; + gss_ctx_id_t context; + gssspnego_ctx ctx; + + memset (&ni, 0, sizeof(ni)); + + *context_handle = GSS_C_NO_CONTEXT; + + *minor_status = 0; + + sub = _gss_spnego_alloc_sec_context(&minor, &context); + if (GSS_ERROR(sub)) { + *minor_status = minor; + return sub; + } + ctx = (gssspnego_ctx)context; + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + ctx->local = 1; + + sub = _gss_spnego_indicate_mechtypelist(&minor, 0, + cred, + &ni.mechTypes, + &ctx->preferred_mech_type); + if (GSS_ERROR(sub)) { + *minor_status = minor; + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return sub; + } + + ni.reqFlags = NULL; + + /* + * If we have a credential handle, use it to select the mechanism + * that we will use + */ + + /* generate optimistic token */ + sub = gss_init_sec_context(&minor, + (cred != NULL) ? cred->negotiated_cred_id : + GSS_C_NO_CREDENTIAL, + &ctx->negotiated_ctx_id, + target_name, + GSS_C_NO_OID, + req_flags, + time_req, + input_chan_bindings, + input_token, + &ctx->negotiated_mech_type, + &mech_token, + &ctx->mech_flags, + &ctx->mech_time_rec); + if (GSS_ERROR(sub)) { + free_NegTokenInit(&ni); + *minor_status = minor; + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return sub; + } + + if (mech_token.length != 0) { + ALLOC(ni.mechToken, 1); + if (ni.mechToken == NULL) { + free_NegTokenInit(&ni); + gss_release_buffer(&minor, &mech_token); + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + ni.mechToken->length = mech_token.length; + ni.mechToken->data = malloc(mech_token.length); + if (ni.mechToken->data == NULL && mech_token.length != 0) { + free_NegTokenInit(&ni); + gss_release_buffer(&minor, &mech_token); + *minor_status = ENOMEM; + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return GSS_S_FAILURE; + } + memcpy(ni.mechToken->data, mech_token.value, mech_token.length); + gss_release_buffer(&minor, &mech_token); + } else + ni.mechToken = NULL; + + ni.mechListMIC = NULL; + + ni_len = length_NegTokenInit(&ni); + buf_size = 1 + der_length_len(ni_len) + ni_len; + + buf = malloc(buf_size); + if (buf == NULL) { + free_NegTokenInit(&ni); + *minor_status = ENOMEM; + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return GSS_S_FAILURE; + } + + ret = encode_NegTokenInit(buf + buf_size - 1, + ni_len, + &ni, &buf_len); + if (ret == 0 && ni_len != buf_len) + abort(); + + if (ret == 0) { + size_t tmp; + + ret = der_put_length_and_tag(buf + buf_size - buf_len - 1, + buf_size - buf_len, + buf_len, + ASN1_C_CONTEXT, + CONS, + 0, + &tmp); + if (ret == 0 && tmp + buf_len != buf_size) + abort(); + } + if (ret) { + *minor_status = ret; + free(buf); + free_NegTokenInit(&ni); + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return GSS_S_FAILURE; + } + + data.value = buf; + data.length = buf_size; + + ctx->initiator_mech_types.len = ni.mechTypes.len; + ctx->initiator_mech_types.val = ni.mechTypes.val; + ni.mechTypes.len = 0; + ni.mechTypes.val = NULL; + + free_NegTokenInit(&ni); + + sub = gss_encapsulate_token(&data, + GSS_SPNEGO_MECHANISM, + output_token); + free (buf); + + if (sub) { + _gss_spnego_internal_delete_sec_context(&minor, &context, GSS_C_NO_BUFFER); + return sub; + } + + if (actual_mech_type) + *actual_mech_type = ctx->negotiated_mech_type; + if (ret_flags) + *ret_flags = ctx->mech_flags; + if (time_rec) + *time_rec = ctx->mech_time_rec; + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + + *context_handle = context; + + return GSS_S_CONTINUE_NEEDED; +} + +static OM_uint32 +spnego_reply + (OM_uint32 * minor_status, + const gssspnego_cred cred, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret, minor; + NegTokenResp resp; + u_char oidbuf[17]; + size_t oidlen; + size_t len, taglen; + gss_OID_desc mech; + int require_mic; + size_t buf_len; + gss_buffer_desc mic_buf, mech_buf; + gss_buffer_desc mech_output_token; + gssspnego_ctx ctx; + + *minor_status = 0; + + ctx = (gssspnego_ctx)*context_handle; + + output_token->length = 0; + output_token->value = NULL; + + mech_output_token.length = 0; + mech_output_token.value = NULL; + + mech_buf.value = NULL; + mech_buf.length = 0; + + ret = der_match_tag_and_length(input_token->value, input_token->length, + ASN1_C_CONTEXT, CONS, 1, &len, &taglen); + if (ret) + return ret; + + if (len > input_token->length - taglen) + return ASN1_OVERRUN; + + ret = decode_NegTokenResp((const unsigned char *)input_token->value+taglen, + len, &resp, NULL); + if (ret) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + if (resp.negResult == NULL + || *(resp.negResult) == reject + || resp.supportedMech == NULL) { + free_NegTokenResp(&resp); + return GSS_S_BAD_MECH; + } + + ret = der_put_oid(oidbuf + sizeof(oidbuf) - 1, + sizeof(oidbuf), + resp.supportedMech, + &oidlen); + if (ret || (oidlen == GSS_SPNEGO_MECHANISM->length && + memcmp(oidbuf + sizeof(oidbuf) - oidlen, + GSS_SPNEGO_MECHANISM->elements, + oidlen) == 0)) { + /* Avoid recursively embedded SPNEGO */ + free_NegTokenResp(&resp); + return GSS_S_BAD_MECH; + } + + HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex); + + if (resp.responseToken != NULL) { + gss_buffer_desc mech_input_token; + + mech_input_token.length = resp.responseToken->length; + mech_input_token.value = resp.responseToken->data; + + mech.length = oidlen; + mech.elements = oidbuf + sizeof(oidbuf) - oidlen; + + /* Fall through as if the negotiated mechanism + was requested explicitly */ + ret = gss_init_sec_context(&minor, + (cred != NULL) ? cred->negotiated_cred_id : + GSS_C_NO_CREDENTIAL, + &ctx->negotiated_ctx_id, + target_name, + &mech, + req_flags, + time_req, + input_chan_bindings, + &mech_input_token, + &ctx->negotiated_mech_type, + &mech_output_token, + &ctx->mech_flags, + &ctx->mech_time_rec); + if (GSS_ERROR(ret)) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + free_NegTokenResp(&resp); + *minor_status = minor; + return ret; + } + if (ret == GSS_S_COMPLETE) { + ctx->open = 1; + } + } + + if (*(resp.negResult) == request_mic) { + ctx->require_mic = 1; + } + + if (ctx->open) { + /* + * Verify the mechListMIC if one was provided or CFX was + * used and a non-preferred mechanism was selected + */ + if (resp.mechListMIC != NULL) { + require_mic = 1; + } else { + ret = _gss_spnego_require_mechlist_mic(minor_status, ctx, + &require_mic); + if (ret) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + free_NegTokenResp(&resp); + gss_release_buffer(&minor, &mech_output_token); + return ret; + } + } + } else { + require_mic = 0; + } + + if (require_mic) { + ASN1_MALLOC_ENCODE(MechTypeList, mech_buf.value, mech_buf.length, + &ctx->initiator_mech_types, &buf_len, ret); + if (ret) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + free_NegTokenResp(&resp); + gss_release_buffer(&minor, &mech_output_token); + *minor_status = ret; + return GSS_S_FAILURE; + } + if (mech_buf.length != buf_len) + abort(); + + if (resp.mechListMIC == NULL) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + free(mech_buf.value); + free_NegTokenResp(&resp); + *minor_status = 0; + return GSS_S_DEFECTIVE_TOKEN; + } + mic_buf.length = resp.mechListMIC->length; + mic_buf.value = resp.mechListMIC->data; + + if (mech_output_token.length == 0) { + ret = gss_verify_mic(minor_status, + ctx->negotiated_ctx_id, + &mech_buf, + &mic_buf, + NULL); + if (ret) { + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + free(mech_buf.value); + gss_release_buffer(&minor, &mech_output_token); + free_NegTokenResp(&resp); + return GSS_S_DEFECTIVE_TOKEN; + } + ctx->verified_mic = 1; + } + } + + ret = spnego_reply_internal(minor_status, ctx, + require_mic ? &mech_buf : NULL, + &mech_output_token, + output_token); + + if (mech_buf.value != NULL) + free(mech_buf.value); + + free_NegTokenResp(&resp); + gss_release_buffer(&minor, &mech_output_token); + + if (actual_mech_type) + *actual_mech_type = ctx->negotiated_mech_type; + if (ret_flags) + *ret_flags = ctx->mech_flags; + if (time_rec) + *time_rec = ctx->mech_time_rec; + + HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex); + return ret; +} + +OM_uint32 _gss_spnego_init_sec_context + (OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + gssspnego_cred cred = (gssspnego_cred)initiator_cred_handle; + + if (*context_handle == GSS_C_NO_CONTEXT) + return spnego_initial (minor_status, + cred, + context_handle, + target_name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + else + return spnego_reply (minor_status, + cred, + context_handle, + target_name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); +} + diff --git a/source4/heimdal/lib/gssapi/spnego/spnego-private.h b/source4/heimdal/lib/gssapi/spnego/spnego-private.h new file mode 100644 index 0000000000..df50f65580 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/spnego-private.h @@ -0,0 +1,347 @@ +/* This is a generated file */ +#ifndef __spnego_private_h__ +#define __spnego_private_h__ + +#include <stdarg.h> + +gssapi_mech_interface +__gss_spnego_initialize (void); + +OM_uint32 +_gss_spnego_accept_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + const gss_cred_id_t /*acceptor_cred_handle*/, + const gss_buffer_t /*input_token_buffer*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + gss_name_t * /*src_name*/, + gss_OID * /*mech_type*/, + gss_buffer_t /*output_token*/, + OM_uint32 * /*ret_flags*/, + OM_uint32 * /*time_rec*/, + gss_cred_id_t *delegated_cred_handle ); + +OM_uint32 +_gss_spnego_acquire_cred ( + OM_uint32 */*minor_status*/, + const gss_name_t /*desired_name*/, + OM_uint32 /*time_req*/, + const gss_OID_set /*desired_mechs*/, + gss_cred_usage_t /*cred_usage*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * time_rec ); + +OM_uint32 +_gss_spnego_add_cred ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*input_cred_handle*/, + const gss_name_t /*desired_name*/, + const gss_OID /*desired_mech*/, + gss_cred_usage_t /*cred_usage*/, + OM_uint32 /*initiator_time_req*/, + OM_uint32 /*acceptor_time_req*/, + gss_cred_id_t * /*output_cred_handle*/, + gss_OID_set * /*actual_mechs*/, + OM_uint32 * /*initiator_time_rec*/, + OM_uint32 * acceptor_time_rec ); + +int +_gss_spnego_add_mech_type ( + gss_OID /*mech_type*/, + int /*includeMSCompatOID*/, + MechTypeList */*mechtypelist*/); + +OM_uint32 +_gss_spnego_alloc_cred ( + OM_uint32 */*minor_status*/, + gss_cred_id_t /*mech_cred_handle*/, + gss_cred_id_t */*cred_handle*/); + +OM_uint32 +_gss_spnego_alloc_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t */*context_handle*/); + +OM_uint32 +_gss_spnego_canonicalize_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + const gss_OID /*mech_type*/, + gss_name_t * output_name ); + +OM_uint32 +_gss_spnego_compare_name ( + OM_uint32 */*minor_status*/, + const gss_name_t /*name1*/, + const gss_name_t /*name2*/, + int * name_equal ); + +OM_uint32 +_gss_spnego_context_time ( + OM_uint32 */*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + OM_uint32 *time_rec ); + +OM_uint32 +_gss_spnego_delete_sec_context ( + OM_uint32 */*minor_status*/, + gss_ctx_id_t */*context_handle*/, + gss_buffer_t output_token ); + +OM_uint32 +_gss_spnego_display_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_buffer_t /*output_name_buffer*/, + gss_OID * output_name_type ); + +OM_uint32 +_gss_spnego_display_status ( + OM_uint32 * /*minor_status*/, + OM_uint32 /*status_value*/, + int /*status_type*/, + const gss_OID /*mech_type*/, + OM_uint32 * /*message_context*/, + gss_buffer_t status_string ); + +OM_uint32 +_gss_spnego_duplicate_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*src_name*/, + gss_name_t * dest_name ); + +OM_uint32 +_gss_spnego_encode_response ( + OM_uint32 */*minor_status*/, + const NegTokenResp */*resp*/, + gss_buffer_t /*data*/, + u_char **/*ret_buf*/); + +OM_uint32 +_gss_spnego_export_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_buffer_t exported_name ); + +OM_uint32 +_gss_spnego_export_sec_context ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + gss_buffer_t interprocess_token ); + +OM_uint32 +_gss_spnego_get_mic ( + OM_uint32 */*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*message_buffer*/, + gss_buffer_t message_token ); + +OM_uint32 +_gss_spnego_import_name ( + OM_uint32 * /*minor_status*/, + const gss_buffer_t /*input_name_buffer*/, + const gss_OID /*input_name_type*/, + gss_name_t * output_name ); + +OM_uint32 +_gss_spnego_import_sec_context ( + OM_uint32 * /*minor_status*/, + const gss_buffer_t /*interprocess_token*/, + gss_ctx_id_t *context_handle ); + +OM_uint32 +_gss_spnego_indicate_mechtypelist ( + OM_uint32 */*minor_status*/, + int /*includeMSCompatOID*/, + const gssspnego_cred /*cred_handle*/, + MechTypeList */*mechtypelist*/, + gss_OID */*preferred_mech*/); + +OM_uint32 +_gss_spnego_init_sec_context ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*initiator_cred_handle*/, + gss_ctx_id_t * /*context_handle*/, + const gss_name_t /*target_name*/, + const gss_OID /*mech_type*/, + OM_uint32 /*req_flags*/, + OM_uint32 /*time_req*/, + const gss_channel_bindings_t /*input_chan_bindings*/, + const gss_buffer_t /*input_token*/, + gss_OID * /*actual_mech_type*/, + gss_buffer_t /*output_token*/, + OM_uint32 * /*ret_flags*/, + OM_uint32 * time_rec ); + +OM_uint32 +_gss_spnego_inquire_context ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + gss_name_t * /*src_name*/, + gss_name_t * /*targ_name*/, + OM_uint32 * /*lifetime_rec*/, + gss_OID * /*mech_type*/, + OM_uint32 * /*ctx_flags*/, + int * /*locally_initiated*/, + int * open_context ); + +OM_uint32 +_gss_spnego_inquire_cred ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + gss_name_t * /*name*/, + OM_uint32 * /*lifetime*/, + gss_cred_usage_t * /*cred_usage*/, + gss_OID_set * mechanisms ); + +OM_uint32 +_gss_spnego_inquire_cred_by_mech ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + const gss_OID /*mech_type*/, + gss_name_t * /*name*/, + OM_uint32 * /*initiator_lifetime*/, + OM_uint32 * /*acceptor_lifetime*/, + gss_cred_usage_t * cred_usage ); + +OM_uint32 +_gss_spnego_inquire_cred_by_oid ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*cred_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t */*data_set*/); + +OM_uint32 +_gss_spnego_inquire_mechs_for_name ( + OM_uint32 * /*minor_status*/, + const gss_name_t /*input_name*/, + gss_OID_set * mech_types ); + +OM_uint32 +_gss_spnego_inquire_names_for_mech ( + OM_uint32 * /*minor_status*/, + const gss_OID /*mechanism*/, + gss_OID_set * name_types ); + +OM_uint32 +_gss_spnego_inquire_sec_context_by_oid ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_OID /*desired_object*/, + gss_buffer_set_t */*data_set*/); + +OM_uint32 +_gss_spnego_internal_delete_sec_context ( + OM_uint32 */*minor_status*/, + gss_ctx_id_t */*context_handle*/, + gss_buffer_t output_token ); + +OM_uint32 +_gss_spnego_process_context_token ( + OM_uint32 */*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t token_buffer ); + +OM_uint32 +_gss_spnego_release_cred ( + OM_uint32 */*minor_status*/, + gss_cred_id_t */*cred_handle*/); + +OM_uint32 +_gss_spnego_release_name ( + OM_uint32 * /*minor_status*/, + gss_name_t * input_name ); + +OM_uint32 +_gss_spnego_require_mechlist_mic ( + OM_uint32 */*minor_status*/, + gssspnego_ctx /*ctx*/, + int */*require_mic*/); + +OM_uint32 +_gss_spnego_seal ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + int /*qop_req*/, + gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t output_message_buffer ); + +OM_uint32 +_gss_spnego_select_mech ( + OM_uint32 */*minor_status*/, + MechType */*mechType*/, + gss_OID */*mech_p*/); + +OM_uint32 +_gss_spnego_set_sec_context_option ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t * /*context_handle*/, + const gss_OID /*desired_object*/, + const gss_buffer_t /*value*/); + +OM_uint32 +_gss_spnego_sign ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + int /*qop_req*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t message_token ); + +OM_uint32 +_gss_spnego_unseal ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + int * qop_state ); + +OM_uint32 +_gss_spnego_unwrap ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t /*input_message_buffer*/, + gss_buffer_t /*output_message_buffer*/, + int * /*conf_state*/, + gss_qop_t * qop_state ); + +OM_uint32 +_gss_spnego_verify ( + OM_uint32 * /*minor_status*/, + gss_ctx_id_t /*context_handle*/, + gss_buffer_t /*message_buffer*/, + gss_buffer_t /*token_buffer*/, + int * qop_state ); + +OM_uint32 +_gss_spnego_verify_mic ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + const gss_buffer_t /*message_buffer*/, + const gss_buffer_t /*token_buffer*/, + gss_qop_t * qop_state ); + +OM_uint32 +_gss_spnego_wrap ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + const gss_buffer_t /*input_message_buffer*/, + int * /*conf_state*/, + gss_buffer_t output_message_buffer ); + +OM_uint32 +_gss_spnego_wrap_size_limit ( + OM_uint32 * /*minor_status*/, + const gss_ctx_id_t /*context_handle*/, + int /*conf_req_flag*/, + gss_qop_t /*qop_req*/, + OM_uint32 /*req_output_size*/, + OM_uint32 * max_input_size ); + +#endif /* __spnego_private_h__ */ diff --git a/source4/heimdal/lib/gssapi/spnego/spnego.asn1 b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 new file mode 100644 index 0000000000..187ce0a0a6 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/spnego.asn1 @@ -0,0 +1,51 @@ +-- $Id: spnego.asn1,v 1.1.1.1 2006/06/28 08:34:45 lha Exp $ + +SPNEGO DEFINITIONS ::= +BEGIN + +MechType::= OBJECT IDENTIFIER + +MechTypeList ::= SEQUENCE OF MechType + +ContextFlags ::= BIT STRING { + delegFlag (0), + mutualFlag (1), + replayFlag (2), + sequenceFlag (3), + anonFlag (4), + confFlag (5), + integFlag (6) +} + +NegHints ::= SEQUENCE { + hintName [0] GeneralString OPTIONAL, + hintAddress [1] OCTET STRING OPTIONAL +} + +NegTokenInit ::= SEQUENCE { + mechTypes [0] MechTypeList, + reqFlags [1] ContextFlags OPTIONAL, + mechToken [2] OCTET STRING OPTIONAL, + negHints [3] NegHints OPTIONAL, + mechListMIC [4] OCTET STRING OPTIONAL + } + +-- NB: negResult is not OPTIONAL in the new SPNEGO spec but +-- Windows clients do not always send it +NegTokenResp ::= SEQUENCE { + negResult [0] ENUMERATED { + accept_completed (0), + accept_incomplete (1), + reject (2), + request-mic (3) } OPTIONAL, + supportedMech [1] MechType OPTIONAL, + responseToken [2] OCTET STRING OPTIONAL, + mechListMIC [3] OCTET STRING OPTIONAL +} + +NegotiationToken ::= CHOICE { + negTokenInit[0] NegTokenInit, + negTokenResp[1] NegTokenResp +} + +END diff --git a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h new file mode 100644 index 0000000000..571bce5569 --- /dev/null +++ b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2004, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* $Id: spnego_locl.h,v 1.11 2006/10/12 06:28:06 lha Exp $ */ + +#ifndef SPNEGO_LOCL_H +#define SPNEGO_LOCL_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_PARAM_H +#include <sys/param.h> +#endif + +#ifdef HAVE_PTHREAD_H +#include <pthread.h> +#endif + +#include <gssapi/gssapi_spnego.h> +#include <gssapi.h> +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#include <heim_threads.h> +#include <asn1_err.h> + +#include <gssapi_mech.h> + +#include "spnego_asn1.h" +#include <der.h> + +#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) + +typedef struct { + gss_cred_id_t negotiated_cred_id; +} *gssspnego_cred; + +typedef struct { + MechTypeList initiator_mech_types; + gss_OID preferred_mech_type; + gss_OID negotiated_mech_type; + gss_ctx_id_t negotiated_ctx_id; + OM_uint32 mech_flags; + OM_uint32 mech_time_rec; + gss_name_t mech_src_name; + gss_cred_id_t delegated_cred_id; + int open : 1; + int local : 1; + int require_mic : 1; + int verified_mic : 1; + HEIMDAL_MUTEX ctx_id_mutex; +} *gssspnego_ctx; + +#include <spnego/spnego-private.h> + +#endif /* SPNEGO_LOCL_H */ diff --git a/source4/heimdal/lib/hdb/db.c b/source4/heimdal/lib/hdb/db.c index 4b4e6e673d..0bbf6f2210 100644 --- a/source4/heimdal/lib/hdb/db.c +++ b/source4/heimdal/lib/hdb/db.c @@ -33,7 +33,7 @@ #include "hdb_locl.h" -RCSID("$Id: db.c,v 1.35 2005/12/13 11:52:55 lha Exp $"); +RCSID("$Id: db.c,v 1.36 2006/09/12 18:12:37 lha Exp $"); #if HAVE_DB1 @@ -47,7 +47,7 @@ static krb5_error_code DB_close(krb5_context context, HDB *db) { DB *d = (DB*)db->hdb_db; - d->close(d); + (*d->close)(d); return 0; } @@ -95,7 +95,7 @@ DB_seq(krb5_context context, HDB *db, code = db->hdb_lock(context, db, HDB_RLOCK); if(code == -1) return HDB_ERR_DB_INUSE; - code = d->seq(d, &key, &value, flag); + code = (*d->seq)(d, &key, &value, flag); db->hdb_unlock(context, db); /* XXX check value */ if(code == -1) return errno; @@ -172,7 +172,7 @@ DB__get(krb5_context context, HDB *db, krb5_data key, krb5_data *reply) code = db->hdb_lock(context, db, HDB_RLOCK); if(code) return code; - code = d->get(d, &k, &v, 0); + code = (*d->get)(d, &k, &v, 0); db->hdb_unlock(context, db); if(code < 0) return errno; @@ -198,7 +198,7 @@ DB__put(krb5_context context, HDB *db, int replace, code = db->hdb_lock(context, db, HDB_WLOCK); if(code) return code; - code = d->put(d, &k, &v, replace ? 0 : R_NOOVERWRITE); + code = (*d->put)(d, &k, &v, replace ? 0 : R_NOOVERWRITE); db->hdb_unlock(context, db); if(code < 0) return errno; @@ -218,7 +218,7 @@ DB__del(krb5_context context, HDB *db, krb5_data key) code = db->hdb_lock(context, db, HDB_WLOCK); if(code) return code; - code = d->del(d, &k, 0); + code = (*d->del)(d, &k, 0); db->hdb_unlock(context, db); if(code == 1) return HDB_ERR_NOENTRY; diff --git a/source4/heimdal/lib/hdb/ext.c b/source4/heimdal/lib/hdb/ext.c index a8995e4138..141c63a8ac 100644 --- a/source4/heimdal/lib/hdb/ext.c +++ b/source4/heimdal/lib/hdb/ext.c @@ -34,7 +34,7 @@ #include "hdb_locl.h" #include <der.h> -RCSID("$Id: ext.c,v 1.2 2006/04/25 10:20:22 lha Exp $"); +RCSID("$Id: ext.c,v 1.6 2006/10/14 10:13:03 lha Exp $"); krb5_error_code hdb_entry_check_mandatory(krb5_context context, const hdb_entry *ent) @@ -220,6 +220,20 @@ hdb_entry_get_pkinit_acl(const hdb_entry *entry, const HDB_Ext_PKINIT_acl **a) } krb5_error_code +hdb_entry_get_pkinit_hash(const hdb_entry *entry, const HDB_Ext_PKINIT_hash **a) +{ + const HDB_extension *ext; + + ext = hdb_find_extension(entry, choice_HDB_extension_data_pkinit_cert_hash); + if (ext) + *a = &ext->data.u.pkinit_cert_hash; + else + *a = NULL; + + return 0; +} + +krb5_error_code hdb_entry_get_pw_change_time(const hdb_entry *entry, time_t *t) { const HDB_extension *ext; @@ -278,7 +292,7 @@ hdb_entry_get_password(krb5_context context, HDB *db, ext->data.u.password.password.length, &pw); } else { - ret = copy_octet_string(&ext->data.u.password.password, &pw); + ret = der_copy_octet_string(&ext->data.u.password.password, &pw); } if (ret) { krb5_clear_error_string(context); @@ -293,7 +307,7 @@ hdb_entry_get_password(krb5_context context, HDB *db, *p = strdup(str); - free_octet_string(&pw); + der_free_octet_string(&pw); if (*p == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; @@ -364,3 +378,19 @@ hdb_entry_clear_password(krb5_context context, hdb_entry *entry) return hdb_clear_extension(context, entry, choice_HDB_extension_data_password); } + +krb5_error_code +hdb_entry_get_ConstrainedDelegACL(const hdb_entry *entry, + const HDB_Ext_Constrained_delegation_acl **a) +{ + const HDB_extension *ext; + + ext = hdb_find_extension(entry, + choice_HDB_extension_data_allowed_to_delegate_to); + if (ext) + *a = &ext->data.u.allowed_to_delegate_to; + else + *a = NULL; + + return 0; +} diff --git a/source4/heimdal/lib/hdb/hdb-protos.h b/source4/heimdal/lib/hdb/hdb-protos.h index 3cc7d2131a..de0545a037 100644 --- a/source4/heimdal/lib/hdb/hdb-protos.h +++ b/source4/heimdal/lib/hdb/hdb-protos.h @@ -71,6 +71,11 @@ hdb_entry_clear_password ( krb5_context /*context*/, hdb_entry */*entry*/); +krb5_error_code +hdb_entry_get_ConstrainedDelegACL ( + const hdb_entry */*entry*/, + const HDB_Ext_Constrained_delegation_acl **/*a*/); + int hdb_entry_get_password ( krb5_context /*context*/, @@ -84,6 +89,11 @@ hdb_entry_get_pkinit_acl ( const HDB_Ext_PKINIT_acl **/*a*/); krb5_error_code +hdb_entry_get_pkinit_hash ( + const hdb_entry */*entry*/, + const HDB_Ext_PKINIT_hash **/*a*/); + +krb5_error_code hdb_entry_get_pw_change_time ( const hdb_entry */*entry*/, time_t */*t*/); diff --git a/source4/heimdal/lib/hdb/hdb.asn1 b/source4/heimdal/lib/hdb/hdb.asn1 index c8a1a34b4f..c8c276ff6e 100644 --- a/source4/heimdal/lib/hdb/hdb.asn1 +++ b/source4/heimdal/lib/hdb/hdb.asn1 @@ -1,4 +1,4 @@ --- $Id: hdb.asn1,v 1.13 2005/08/11 13:15:44 lha Exp $ +-- $Id: hdb.asn1,v 1.17 2006/08/24 10:45:19 lha Exp $ HDB DEFINITIONS ::= BEGIN @@ -41,7 +41,10 @@ HDBFlags ::= BIT STRING { require-hwauth(10), -- must use hwauth ok-as-delegate(11), -- as in TicketFlags user-to-user(12), -- may use user-to-user auth - immutable(13) -- may not be deleted + immutable(13), -- may not be deleted + trusted-for-delegation(14), -- Trusted to print forwardabled tickets + allow-kerberos4(15), -- Allow Kerberos 4 requests + allow-digest(16) -- Allow digest requests } GENERATION ::= SEQUENCE { @@ -52,10 +55,14 @@ GENERATION ::= SEQUENCE { HDB-Ext-PKINIT-acl ::= SEQUENCE OF SEQUENCE { subject[0] UTF8String, - issuer[1] UTF8String + issuer[1] UTF8String OPTIONAL, + anchor[2] UTF8String OPTIONAL } -HDB-Ext-PKINIT-certificate ::= SEQUENCE OF OCTET STRING +HDB-Ext-PKINIT-hash ::= SEQUENCE OF SEQUENCE { + digest-type[0] OBJECT IDENTIFIER, + digest[1] OCTET STRING +} HDB-Ext-Constrained-delegation-acl ::= SEQUENCE OF Principal @@ -80,7 +87,7 @@ HDB-extension ::= SEQUENCE { -- be rejected data[1] CHOICE { pkinit-acl[0] HDB-Ext-PKINIT-acl, - pkinit-cert[1] HDB-Ext-PKINIT-certificate, + pkinit-cert-hash[1] HDB-Ext-PKINIT-hash, allowed-to-delegate-to[2] HDB-Ext-Constrained-delegation-acl, -- referral-info[3] HDB-Ext-Referrals, lm-owf[4] HDB-Ext-Lan-Manager-OWF, diff --git a/source4/heimdal/lib/hdb/hdb.c b/source4/heimdal/lib/hdb/hdb.c index 555a0d53f6..d1fa4ffd6a 100644 --- a/source4/heimdal/lib/hdb/hdb.c +++ b/source4/heimdal/lib/hdb/hdb.c @@ -33,7 +33,7 @@ #include "hdb_locl.h" -RCSID("$Id: hdb.c,v 1.61 2006/04/24 20:57:58 lha Exp $"); +RCSID("$Id: hdb.c,v 1.62 2006/10/06 16:47:22 lha Exp $"); #ifdef HAVE_DLFCN_H #include <dlfcn.h> @@ -58,6 +58,9 @@ static struct hdb_method methods[] = { #ifdef _SAMBA_BUILD_ {"ldb:", hdb_ldb_create}, #endif +#ifdef HAVE_LDB /* Used for integrated samba build */ + {"ldb:", hdb_ldb_create}, +#endif {NULL, NULL} }; @@ -262,7 +265,7 @@ find_dynamic_method (krb5_context context, if (prefix == NULL) krb5_errx(context, 1, "out of memory"); - if (asprintf(&path, HDBDIR "/hdb_%s.so", prefix) == -1) + if (asprintf(&path, LIBDIR "/hdb_%s.so", prefix) == -1) krb5_errx(context, 1, "out of memory"); #ifndef RTLD_NOW @@ -398,6 +401,6 @@ hdb_create(krb5_context context, HDB **db, const char *filename) h = find_dynamic_method (context, filename, &residual); #endif if (h == NULL) - krb5_errx(context, 1, "No database support! (hdb_create(%s))", filename); + krb5_errx(context, 1, "No database support for %s", filename); return (*h->create)(context, db, residual); } diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h index d14eea7ddc..69c91d12ad 100644 --- a/source4/heimdal/lib/hdb/hdb.h +++ b/source4/heimdal/lib/hdb/hdb.h @@ -66,17 +66,17 @@ typedef struct hdb_entry_ex { struct hdb_entry_ex *, METHOD_DATA* pa_data_seq, time_t authtime, - EncryptionKey *tgtkey, - EncryptionKey *sessionkey, + const EncryptionKey *tgtkey, + const EncryptionKey *sessionkey, AuthorizationData **out); krb5_error_code (*authz_data_tgs_req)(krb5_context, struct hdb_entry_ex *, krb5_principal client, AuthorizationData *in, time_t authtime, - EncryptionKey *tgtkey, - EncryptionKey *servicekey, - EncryptionKey *sessionkey, + const EncryptionKey *tgtkey, + const EncryptionKey *servicekey, + const EncryptionKey *sessionkey, AuthorizationData **out); } hdb_entry_ex; diff --git a/source4/heimdal/lib/hdb/keys.c b/source4/heimdal/lib/hdb/keys.c index d7c2f2c89b..8d4810f5c9 100644 --- a/source4/heimdal/lib/hdb/keys.c +++ b/source4/heimdal/lib/hdb/keys.c @@ -33,7 +33,7 @@ #include "hdb_locl.h" -RCSID("$Id: keys.c,v 1.5 2006/04/25 08:09:38 lha Exp $"); +RCSID("$Id: keys.c,v 1.6 2006/10/22 09:40:12 lha Exp $"); /* * free all the memory used by (len, keys) @@ -334,6 +334,9 @@ hdb_generate_key_set(krb5_context context, krb5_principal principal, *ret_key_set = key_set; out: + if (ktypes != default_keytypes) + krb5_config_free_strings(ktypes); + if (ret) { krb5_warn(context, ret, "failed to parse the [kadmin]default_keys values"); diff --git a/source4/heimdal/lib/hdb/keytab.c b/source4/heimdal/lib/hdb/keytab.c index c87b8eca2c..8f473a68a4 100644 --- a/source4/heimdal/lib/hdb/keytab.c +++ b/source4/heimdal/lib/hdb/keytab.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999 - 2002 Kungliga Tekniska Högskolan + * Copyright (c) 1999 - 2002 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -35,7 +35,7 @@ /* keytab backend for HDB databases */ -RCSID("$Id: keytab.c,v 1.11 2006/04/27 11:01:30 lha Exp $"); +RCSID("$Id: keytab.c,v 1.16 2006/10/09 12:36:40 lha Exp $"); struct hdb_data { char *dbname; @@ -59,7 +59,7 @@ hdb_resolve(krb5_context context, const char *name, krb5_keytab id) return ENOMEM; } db = name; - mkey = strrchr(name, ':'); + mkey = strchr(name, ':'); if(mkey == NULL || mkey[1] == '\0') { if(*name == '\0') d->dbname = NULL; @@ -201,6 +201,8 @@ hdb_get_entry(krb5_context context, const char *dbname = d->dbname; const char *mkey = d->mkey; + memset(&ent, 0, sizeof(ent)); + if (dbname == NULL) find_db (context, &dbname, &mkey, principal); @@ -218,26 +220,21 @@ hdb_get_entry(krb5_context context, (*db->hdb_destroy)(context, db); return ret; } - ret = (*db->hdb_fetch)(context, db, principal, HDB_F_DECRYPT|HDB_F_GET_CLIENT|HDB_F_GET_SERVER, &ent); - + ret = (*db->hdb_fetch)(context, db, principal, + HDB_F_DECRYPT| + HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT, + &ent); - /* Shutdown the hdb on error */ if(ret == HDB_ERR_NOENTRY) { - (*db->hdb_close)(context, db); - (*db->hdb_destroy)(context, db); - return KRB5_KT_NOTFOUND; - } else if (ret) { - (*db->hdb_close)(context, db); - (*db->hdb_destroy)(context, db); - return ret; - } + ret = KRB5_KT_NOTFOUND; + goto out; + }else if(ret) + goto out; + if(kvno && ent.entry.kvno != kvno) { - /* The order here matters, we must free these in this order - * due to hdb-ldb and Samba4's talloc */ hdb_free_entry(context, &ent); - (*db->hdb_close)(context, db); - (*db->hdb_destroy)(context, db); - return KRB5_KT_NOTFOUND; + ret = KRB5_KT_NOTFOUND; + goto out; } if(enctype == 0) if(ent.entry.keys.len > 0) @@ -254,9 +251,8 @@ hdb_get_entry(krb5_context context, break; } } - /* The order here matters, we must free these in this order - * due to hdb-ldb and Samba4's talloc */ hdb_free_entry(context, &ent); +out: (*db->hdb_close)(context, db); (*db->hdb_destroy)(context, db); return ret; diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c index b38104fc2d..004926bc89 100644 --- a/source4/heimdal/lib/krb5/acache.c +++ b/source4/heimdal/lib/krb5/acache.c @@ -37,7 +37,7 @@ #include <dlfcn.h> #endif -RCSID("$Id: acache.c,v 1.15 2006/03/27 04:22:23 lha Exp $"); +RCSID("$Id: acache.c,v 1.16 2006/10/19 11:41:38 lha Exp $"); /* XXX should we fetch these for each open ? */ static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; @@ -113,7 +113,7 @@ init_ccapi(krb5_context context) return KRB5_CC_NOSUPP; } - init_func = dlsym(cc_handle, "cc_initialize"); + init_func = (cc_initialize_func)dlsym(cc_handle, "cc_initialize"); HEIMDAL_MUTEX_unlock(&acc_mutex); if (init_func == NULL) { krb5_set_error_string(context, "Failed to find cc_initialize" diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c index 895b01f9d8..f68be423b0 100644 --- a/source4/heimdal/lib/krb5/addr_families.c +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: addr_families.c,v 1.52 2006/05/05 09:26:22 lha Exp $"); +RCSID("$Id: addr_families.c,v 1.53 2006/10/22 06:54:00 lha Exp $"); struct addr_operations { int af; @@ -551,6 +551,7 @@ arange_free (krb5_context context, krb5_address *addr) a = addr->address.data; krb5_free_address(context, &a->low); krb5_free_address(context, &a->high); + krb5_data_free(&addr->address); return 0; } diff --git a/source4/heimdal/lib/krb5/asn1_glue.c b/source4/heimdal/lib/krb5/asn1_glue.c index 8f7b886e80..b07e058550 100644 --- a/source4/heimdal/lib/krb5/asn1_glue.c +++ b/source4/heimdal/lib/krb5/asn1_glue.c @@ -37,7 +37,7 @@ #include "krb5_locl.h" -RCSID("$Id: asn1_glue.c,v 1.9 2004/12/29 18:54:15 lha Exp $"); +RCSID("$Id: asn1_glue.c,v 1.10 2006/10/06 17:02:48 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION _krb5_principal2principalname (PrincipalName *p, diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index b21d42d653..a96870a7de 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c,v 1.79 2006/04/02 00:54:48 lha Exp $"); +RCSID("$Id: cache.c,v 1.82 2006/09/12 17:35:33 lha Exp $"); /* * Add a new ccache type with operations `ops', overwriting any @@ -188,7 +188,7 @@ krb5_cc_new_unique(krb5_context context, const char *type, const krb5_cc_ops *ops; if (type == NULL) - type = "FILE"; + type = KRB5_DEFAULT_CCNAME; ops = krb5_cc_get_prefix_ops(context, type); if (ops == NULL) { @@ -423,7 +423,7 @@ krb5_cc_initialize(krb5_context context, krb5_ccache id, krb5_principal primary_principal) { - return id->ops->init(context, id, primary_principal); + return (*id->ops->init)(context, id, primary_principal); } @@ -438,7 +438,7 @@ krb5_cc_destroy(krb5_context context, { krb5_error_code ret; - ret = id->ops->destroy(context, id); + ret = (*id->ops->destroy)(context, id); krb5_cc_close (context, id); return ret; } @@ -453,7 +453,7 @@ krb5_cc_close(krb5_context context, krb5_ccache id) { krb5_error_code ret; - ret = id->ops->close(context, id); + ret = (*id->ops->close)(context, id); free(id); return ret; } @@ -468,7 +468,7 @@ krb5_cc_store_cred(krb5_context context, krb5_ccache id, krb5_creds *creds) { - return id->ops->store(context, id, creds); + return (*id->ops->store)(context, id, creds); } /* @@ -488,8 +488,8 @@ krb5_cc_retrieve_cred(krb5_context context, krb5_cc_cursor cursor; if (id->ops->retrieve != NULL) { - return id->ops->retrieve(context, id, whichfields, - mcreds, creds); + return (*id->ops->retrieve)(context, id, whichfields, + mcreds, creds); } krb5_cc_start_seq_get(context, id, &cursor); @@ -514,7 +514,7 @@ krb5_cc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *principal) { - return id->ops->get_princ(context, id, principal); + return (*id->ops->get_princ)(context, id, principal); } /* @@ -528,7 +528,7 @@ krb5_cc_start_seq_get (krb5_context context, const krb5_ccache id, krb5_cc_cursor *cursor) { - return id->ops->get_first(context, id, cursor); + return (*id->ops->get_first)(context, id, cursor); } /* @@ -543,7 +543,7 @@ krb5_cc_next_cred (krb5_context context, krb5_cc_cursor *cursor, krb5_creds *creds) { - return id->ops->get_next(context, id, cursor, creds); + return (*id->ops->get_next)(context, id, cursor, creds); } /* like krb5_cc_next_cred, but allow for selective retrieval */ @@ -576,7 +576,7 @@ krb5_cc_end_seq_get (krb5_context context, const krb5_ccache id, krb5_cc_cursor *cursor) { - return id->ops->end_get(context, id, cursor); + return (*id->ops->end_get)(context, id, cursor); } /* @@ -607,7 +607,7 @@ krb5_cc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags) { - return id->ops->set_flags(context, id, flags); + return (*id->ops->set_flags)(context, id, flags); } /* @@ -672,7 +672,7 @@ krb5_cc_get_version(krb5_context context, const krb5_ccache id) { if(id->ops->get_version) - return id->ops->get_version(context, id); + return (*id->ops->get_version)(context, id); else return 0; } diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index 594665235b..f7b3ffbf9e 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include <com_err.h> -RCSID("$Id: context.c,v 1.102 2005/05/18 04:20:50 lha Exp $"); +RCSID("$Id: context.c,v 1.108 2006/10/20 22:26:10 lha Exp $"); #define INIT_FIELD(C, T, E, D, F) \ (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ @@ -181,8 +181,8 @@ init_context_from_config_file(krb5_context context) INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); INIT_FIELD(context, int, large_msg_size, 6000, "large_message_size"); + INIT_FIELD(context, bool, dns_canonicalize_hostname, TRUE, "dns_canonize_hostname"); context->default_cc_name = NULL; - INIT_FIELD(context, bool, fdns, TRUE, "fdns"); return 0; } @@ -263,7 +263,7 @@ krb5_free_context(krb5_context context) krb5_closelog(context, context->warn_dest); krb5_set_extra_addresses(context, NULL); krb5_set_ignore_addresses(context, NULL); - free(context->send_and_recv); + krb5_set_send_to_kdc_func(context, NULL, NULL); if (context->mutex != NULL) { HEIMDAL_MUTEX_destroy(context->mutex); free(context->mutex); @@ -424,13 +424,17 @@ krb5_free_config_files(char **filenames) } /* - * set `etype' to a malloced list of the default enctypes + * Returns the list of Kerberos encryption types sorted in order of + * most preferred to least preferred encryption type. The array ends + * with ETYPE_NULL. Note that some encryption types might be + * disabled, so you need to check with krb5_enctype_valid() before + * using the encryption type. */ -static krb5_error_code -default_etypes(krb5_context context, krb5_enctype **etype) +const krb5_enctype * KRB5_LIB_FUNCTION +krb5_kerberos_enctypes(krb5_context context) { - krb5_enctype p[] = { + static const krb5_enctype p[] = { ETYPE_AES256_CTS_HMAC_SHA1_96, ETYPE_AES128_CTS_HMAC_SHA1_96, ETYPE_DES3_CBC_SHA1, @@ -438,12 +442,26 @@ default_etypes(krb5_context context, krb5_enctype **etype) ETYPE_ARCFOUR_HMAC_MD5, ETYPE_DES_CBC_MD5, ETYPE_DES_CBC_MD4, - ETYPE_DES_CBC_CRC + ETYPE_DES_CBC_CRC, + ETYPE_NULL }; + return p; +} + +/* + * set `etype' to a malloced list of the default enctypes + */ + +static krb5_error_code +default_etypes(krb5_context context, krb5_enctype **etype) +{ + const krb5_enctype *p; krb5_enctype *e = NULL, *ep; int i, n = 0; - for (i = 0; i < sizeof(p)/sizeof(p[0]); i++) { + p = krb5_kerberos_enctypes(context); + + for (i = 0; p[i] != ETYPE_NULL; i++) { if (krb5_enctype_valid(context, p[i]) != 0) continue; ep = realloc(e, (n + 2) * sizeof(*e)); @@ -537,6 +555,9 @@ krb5_init_ets(krb5_context context) krb5_add_et_list(context, initialize_asn1_error_table_r); krb5_add_et_list(context, initialize_heim_error_table_r); krb5_add_et_list(context, initialize_k524_error_table_r); +#ifdef PKINIT + krb5_add_et_list(context, initialize_hx_error_table_r); +#endif } } @@ -662,3 +683,25 @@ krb5_is_thread_safe(void) return FALSE; #endif } + +void KRB5_LIB_FUNCTION +krb5_set_dns_canonicalize_hostname (krb5_context context, krb5_boolean flag) +{ + context->dns_canonicalize_hostname = flag; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_get_dns_canonize_hostname (krb5_context context) +{ + return context->dns_canonicalize_hostname; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec) +{ + if (sec) + *sec = context->kdc_sec_offset; + if (usec) + *usec = context->kdc_usec_offset; + return 0; +} diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index a3c58051f9..9f6ef6b82b 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.138 2006/05/08 13:47:24 lha Exp $"); +RCSID("$Id: crypto.c,v 1.145 2006/10/22 07:32:40 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -55,7 +55,6 @@ struct krb5_crypto_data { struct key_data key; int num_key_usage; struct key_usage *key_usage; - void *params; }; #define kcrypto_oid_enc(n) { sizeof(n)/sizeof(n[0]), n } @@ -89,13 +88,9 @@ struct key_type { krb5_enctype best_etype; #endif void (*random_key)(krb5_context, krb5_keyblock*); - void (*schedule)(krb5_context, struct key_data *, const void *); + void (*schedule)(krb5_context, struct key_data *); struct salt_type *string_to_key; void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t); - krb5_error_code (*get_params)(krb5_context, const krb5_data *, - void **, krb5_data *); - krb5_error_code (*set_params)(krb5_context, const void *, - const krb5_data *, krb5_data *); }; struct checksum_type { @@ -181,8 +176,7 @@ krb5_DES_random_key(krb5_context context, static void krb5_DES_schedule(krb5_context context, - struct key_data *key, - const void *params) + struct key_data *key) { DES_set_key(key->key->keyvalue.data, key->schedule->data); } @@ -392,8 +386,7 @@ DES3_random_key(krb5_context context, static void DES3_schedule(krb5_context context, - struct key_data *key, - const void *params) + struct key_data *key) { DES_cblock *k = key->key->keyvalue.data; DES_key_schedule *s = key->schedule->data; @@ -546,8 +539,7 @@ DES3_random_to_key(krb5_context context, static void ARCFOUR_schedule(krb5_context context, - struct key_data *kd, - const void *params) + struct key_data *kd) { RC4_set_key (kd->schedule->data, kd->key->keyvalue.length, kd->key->keyvalue.data); @@ -618,15 +610,16 @@ AES_string_to_key(krb5_context context, if (et == NULL) return KRB5_PROG_KEYTYPE_NOSUPP; - key->keytype = enctype; - ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); - if (ret) { - krb5_set_error_string(context, "Failed to allocate pkcs5 key"); - return ret; + kd.schedule = NULL; + ALLOC(kd.key, 1); + if(kd.key == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; } - ret = krb5_copy_keyblock(context, key, &kd.key); + kd.key->keytype = enctype; + ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); if (ret) { - krb5_free_keyblock(context, key); + krb5_set_error_string(context, "Failed to allocate pkcs5 key"); return ret; } @@ -634,8 +627,8 @@ AES_string_to_key(krb5_context context, salt.saltvalue.data, salt.saltvalue.length, iter, et->keytype->size, kd.key->keyvalue.data); - kd.schedule = NULL; if (ret != 1) { + free_key_data(context, &kd); krb5_set_error_string(context, "Error calculating s2k"); return KRB5_PROG_KEYTYPE_NOSUPP; } @@ -655,8 +648,7 @@ struct krb5_aes_schedule { static void AES_schedule(krb5_context context, - struct key_data *kd, - const void *params) + struct key_data *kd) { struct krb5_aes_schedule *key = kd->schedule->data; int bits = kd->key->keyvalue.length * 8; @@ -667,115 +659,6 @@ AES_schedule(krb5_context context, } /* - * RC2 - */ - -struct _RC2_params { - int maximum_effective_key; -}; - -static krb5_error_code -rc2_get_params(krb5_context context, - const krb5_data *data, - void **params, - krb5_data *ivec) -{ - RC2CBCParameter rc2params; - struct _RC2_params *p; - krb5_error_code ret; - size_t size; - - ret = decode_RC2CBCParameter(data->data, data->length, &rc2params, &size); - if (ret) { - krb5_set_error_string(context, "Can't decode RC2 parameters"); - return ret; - } - p = malloc(sizeof(*p)); - if (p == NULL) { - free_RC2CBCParameter(&rc2params); - krb5_set_error_string(context, "malloc - out of memory"); - return ENOMEM; - } - /* XXX */ - switch(rc2params.rc2ParameterVersion) { - case 160: - p->maximum_effective_key = 40; - break; - case 120: - p->maximum_effective_key = 64; - break; - case 58: - p->maximum_effective_key = 128; - break; - - } - if (ivec) - ret = copy_octet_string(&rc2params.iv, ivec); - free_RC2CBCParameter(&rc2params); - *params = p; - - return ret; -} - -static krb5_error_code -rc2_set_params(krb5_context context, - const void *params, - const krb5_data *ivec, - krb5_data *data) -{ - RC2CBCParameter rc2params; - const struct _RC2_params *p = params; - int maximum_effective_key = 128; - krb5_error_code ret; - size_t size; - - memset(&rc2params, 0, sizeof(rc2params)); - - if (p) - maximum_effective_key = p->maximum_effective_key; - - /* XXX */ - switch(maximum_effective_key) { - case 40: - rc2params.rc2ParameterVersion = 160; - break; - case 64: - rc2params.rc2ParameterVersion = 120; - break; - case 128: - rc2params.rc2ParameterVersion = 58; - break; - } - ret = copy_octet_string(ivec, &rc2params.iv); - if (ret) - return ret; - - ASN1_MALLOC_ENCODE(RC2CBCParameter, data->data, data->length, - &rc2params, &size, ret); - if (ret == 0 && size != data->length) - krb5_abortx(context, "Internal asn1 encoder failure"); - free_RC2CBCParameter(&rc2params); - - return ret; -} - -static void -rc2_schedule(krb5_context context, - struct key_data *kd, - const void *params) -{ - const struct _RC2_params *p = params; - int maximum_effective_key = 128; - if (p) - maximum_effective_key = p->maximum_effective_key; - RC2_set_key (kd->schedule->data, - kd->key->keyvalue.length, - kd->key->keyvalue.data, - maximum_effective_key); -} - - -/* * */ @@ -898,18 +781,6 @@ static struct key_type keytype_aes128 = { AES_salt }; -static struct key_type keytype_aes192 = { - KEYTYPE_AES192, - "aes-192", - 192, - 24, - 24, - sizeof(struct krb5_aes_schedule), - NULL, - AES_schedule, - AES_salt -}; - static struct key_type keytype_aes256 = { KEYTYPE_AES256, "aes-256", @@ -934,30 +805,13 @@ static struct key_type keytype_arcfour = { arcfour_salt }; -static struct key_type keytype_rc2 = { - KEYTYPE_RC2, - "rc2", - 128, - 16, - 1, - sizeof(RC2_KEY), - NULL, - rc2_schedule, - NULL, /* XXX salt */ - NULL, - rc2_get_params, - rc2_set_params -}; - static struct key_type *keytypes[] = { &keytype_null, &keytype_des, &keytype_des3_derived, &keytype_des3, &keytype_aes128, - &keytype_aes192, &keytype_aes256, - &keytype_rc2, &keytype_arcfour }; @@ -1247,8 +1101,7 @@ krb5_generate_random_keyblock(krb5_context context, static krb5_error_code _key_schedule(krb5_context context, - struct key_data *key, - const void *params) + struct key_data *key) { krb5_error_code ret; struct encryption_type *et = _find_enctype(key->key->keytype); @@ -1269,7 +1122,7 @@ _key_schedule(krb5_context context, key->schedule = NULL; return ret; } - (*kt->schedule)(context, key, params); + (*kt->schedule)(context, key); return 0; } @@ -1933,7 +1786,7 @@ get_checksum_key(krb5_context context, *key = &crypto->key; } if(ret == 0) - ret = _key_schedule(context, *key, crypto->params); + ret = _key_schedule(context, *key); return ret; } @@ -2290,16 +2143,15 @@ DES_PCBC_encrypt_key_ivec(krb5_context context, void KRB5_LIB_FUNCTION _krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out, - size_t len, const void *aes_key, + size_t len, const AES_KEY *key, unsigned char *ivec, const int encryptp) { unsigned char tmp[AES_BLOCK_SIZE]; - const AES_KEY *key = aes_key; /* XXX remove this when we always have AES */ int i; /* * In the framework of kerberos, the length can never be shorter - * than at least one blocksize. + * then at least one blocksize. */ if (encryptp) { @@ -2838,7 +2690,7 @@ krb5_string_to_enctype(krb5_context context, } krb5_error_code KRB5_LIB_FUNCTION -krb5_enctype_to_oid(krb5_context context, +_krb5_enctype_to_oid(krb5_context context, krb5_enctype etype, heim_oid *oid) { @@ -2853,7 +2705,7 @@ krb5_enctype_to_oid(krb5_context context, return KRB5_PROG_ETYPE_NOSUPP; } krb5_clear_error_string(context); - return copy_oid(et->oid, oid); + return der_copy_oid(et->oid, oid); } krb5_error_code KRB5_LIB_FUNCTION @@ -2863,7 +2715,7 @@ _krb5_oid_to_enctype(krb5_context context, { int i; for(i = 0; i < num_etypes; i++) { - if(etypes[i]->oid && heim_oid_cmp(etypes[i]->oid, oid) == 0) { + if(etypes[i]->oid && der_heim_oid_cmp(etypes[i]->oid, oid) == 0) { *etype = etypes[i]->type; return 0; } @@ -3080,7 +2932,7 @@ encrypt_internal_derived(krb5_context context, ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); if(ret) goto fail; - ret = _key_schedule(context, dkey, crypto->params); + ret = _key_schedule(context, dkey); if(ret) goto fail; #ifdef CRYPTO_DEBUG @@ -3146,7 +2998,7 @@ encrypt_internal(krb5_context context, goto fail; memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length); free_Checksum(&cksum); - ret = _key_schedule(context, &crypto->key, crypto->params); + ret = _key_schedule(context, &crypto->key); if(ret) goto fail; #ifdef CRYPTO_DEBUG @@ -3246,7 +3098,7 @@ decrypt_internal_derived(krb5_context context, free(p); return ret; } - ret = _key_schedule(context, dkey, crypto->params); + ret = _key_schedule(context, dkey); if(ret) { free(p); return ret; @@ -3313,7 +3165,7 @@ decrypt_internal(krb5_context context, } memcpy(p, data, len); - ret = _key_schedule(context, &crypto->key, crypto->params); + ret = _key_schedule(context, &crypto->key); if(ret) { free(p); return ret; @@ -3613,11 +3465,9 @@ derive_key(krb5_context context, unsigned char *k; unsigned int nblocks = 0, i; krb5_error_code ret = 0; - struct key_type *kt = et->keytype; - /* since RC2 is only the weird crypto alg with parameter and this - * function not defined with work with RC2, this is ok */ - ret = _key_schedule(context, key, NULL); + + ret = _key_schedule(context, key); if(ret) return ret; if(et->blocksize * 8 < kt->bits || @@ -3795,7 +3645,6 @@ krb5_crypto_init(krb5_context context, (*crypto)->key.schedule = NULL; (*crypto)->num_key_usage = 0; (*crypto)->key_usage = NULL; - (*crypto)->params = NULL; return 0; } @@ -3825,80 +3674,11 @@ krb5_crypto_destroy(krb5_context context, free_key_usage(context, &crypto->key_usage[i]); free(crypto->key_usage); free_key_data(context, &crypto->key); - free(crypto->params); free (crypto); return 0; } krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_get_params(krb5_context context, - const krb5_crypto crypto, - const krb5_data *params, - krb5_data *ivec) -{ - krb5_error_code (*gp)(krb5_context, const krb5_data *,void **,krb5_data *); - krb5_error_code ret; - - gp = crypto->et->keytype->get_params; - if (gp) { - if (crypto->params) { - krb5_set_error_string(context, - "krb5_crypto_get_params called " - "more than once"); - return KRB5_PROG_ETYPE_NOSUPP; - } - ret = (*gp)(context, params, &crypto->params, ivec); - } else { - size_t size; - if (ivec == NULL) - return 0; - ret = decode_CBCParameter(params->data, params->length, ivec, &size); - } - if (ret) - return ret; - if (ivec->length < crypto->et->blocksize) { - krb5_data_free(ivec); - krb5_set_error_string(context, "%s IV of wrong size", - crypto->et->name); - return ASN1_PARSE_ERROR; - } - return 0; -} - -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_set_params(krb5_context context, - const krb5_crypto crypto, - const krb5_data *ivec, - krb5_data *params) -{ - krb5_error_code (*sp)(krb5_context, const void *, - const krb5_data *, krb5_data *); - krb5_error_code ret; - - sp = crypto->et->keytype->set_params; - if (sp == NULL) { - size_t size; - if (ivec == NULL) - return 0; - ASN1_MALLOC_ENCODE(CBCParameter, params->data, params->length, - ivec, &size, ret); - if (ret) - return ret; - if (size != params->length) - krb5_abortx(context, "Internal asn1 encoder failure"); - return 0; - } - if (crypto->params) { - krb5_set_error_string(context, - "krb5_crypto_set_params called " - "more than once"); - return KRB5_PROG_ETYPE_NOSUPP; - } - return (*sp)(context, crypto->params, ivec, params); -} - - -krb5_error_code KRB5_LIB_FUNCTION krb5_crypto_getblocksize(krb5_context context, krb5_crypto crypto, size_t *blocksize) diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c index 3192c4c64f..f0c6d00abe 100644 --- a/source4/heimdal/lib/krb5/data.c +++ b/source4/heimdal/lib/krb5/data.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: data.c,v 1.20 2006/04/02 01:06:07 lha Exp $"); +RCSID("$Id: data.c,v 1.21 2006/10/14 09:45:41 lha Exp $"); void KRB5_LIB_FUNCTION krb5_data_zero(krb5_data *p) @@ -110,7 +110,7 @@ krb5_copy_data(krb5_context context, krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - ret = copy_octet_string(indata, *outdata); + ret = der_copy_octet_string(indata, *outdata); if(ret) { krb5_clear_error_string (context); free(*outdata); diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c index f03bf15807..4d0692bcfa 100644 --- a/source4/heimdal/lib/krb5/expand_hostname.c +++ b/source4/heimdal/lib/krb5/expand_hostname.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: expand_hostname.c,v 1.12 2004/05/25 21:24:14 lha Exp $"); +RCSID("$Id: expand_hostname.c,v 1.13 2006/10/17 09:16:32 lha Exp $"); static krb5_error_code copy_hostname(krb5_context context, @@ -62,13 +62,12 @@ krb5_expand_hostname (krb5_context context, struct addrinfo *ai, *a, hints; int error; + if (!context->dns_canonicalize_hostname) + return copy_hostname (context, orig_hostname, new_hostname); + memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; - if (!context->fdns) { - return copy_hostname (context, orig_hostname, new_hostname); - } - error = getaddrinfo (orig_hostname, NULL, &hints, &ai); if (error) return copy_hostname (context, orig_hostname, new_hostname); @@ -128,10 +127,9 @@ krb5_expand_hostname_realms (krb5_context context, int error; krb5_error_code ret = 0; - if (!context->fdns) { + if (!context->dns_canonicalize_hostname) return vanilla_hostname (context, orig_hostname, new_hostname, realms); - } memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 1fa3f9143e..b404c30f6e 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -33,7 +33,7 @@ #include <krb5_locl.h> -RCSID("$Id: get_cred.c,v 1.109 2006/02/03 11:41:02 lha Exp $"); +RCSID("$Id: get_cred.c,v 1.112 2006/06/06 21:22:54 lha Exp $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -142,6 +142,7 @@ init_tgs_req (krb5_context context, krb5_creds *in_creds, krb5_creds *krbtgt, unsigned nonce, + const METHOD_DATA *padata, krb5_keyblock **subkey, TGS_REQ *t, krb5_key_usage usage) @@ -220,12 +221,22 @@ init_tgs_req (krb5_context context, krb5_set_error_string(context, "malloc: out of memory"); goto fail; } - ALLOC_SEQ(t->padata, 1); + ALLOC_SEQ(t->padata, 1 + padata->len); if (t->padata->val == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } + { + int i; + for (i = 0; i < padata->len; i++) { + ret = copy_PA_DATA(&padata->val[i], &t->padata->val[i + 1]); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + } + } { krb5_auth_context ac; @@ -268,7 +279,7 @@ init_tgs_req (krb5_context context, ret = make_pa_tgs_req(context, ac, &t->req_body, - t->padata->val, + &t->padata->val[0], krbtgt, usage); if(ret) { @@ -383,8 +394,10 @@ get_cred_kdc_usage(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, krb5_addresses *addresses, - krb5_creds *in_creds, + krb5_creds *in_creds, krb5_creds *krbtgt, + krb5_principal impersonate_principal, + Ticket *second_ticket, krb5_creds *out_creds, krb5_key_usage usage) { @@ -397,36 +410,91 @@ get_cred_kdc_usage(krb5_context context, unsigned nonce; krb5_keyblock *subkey = NULL; size_t len; - Ticket second_ticket; + Ticket second_ticket_data; int send_to_kdc_flags = 0; + METHOD_DATA padata; krb5_data_zero(&resp); krb5_data_zero(&enc); + padata.val = NULL; + padata.len = 0; krb5_generate_random_block(&nonce, sizeof(nonce)); nonce &= 0xffffffff; - if(flags.b.enc_tkt_in_skey){ + if(flags.b.enc_tkt_in_skey && second_ticket == NULL){ ret = decode_Ticket(in_creds->second_ticket.data, in_creds->second_ticket.length, - &second_ticket, &len); + &second_ticket_data, &len); if(ret) return ret; + second_ticket = &second_ticket_data; + } + + + if (impersonate_principal) { + krb5_crypto crypto; + PA_S4U2Self self; + krb5_data data; + void *buf; + size_t size; + + self.name = impersonate_principal->name; + self.realm = impersonate_principal->realm; + self.auth = estrdup("Kerberos"); + + ret = _krb5_s4u2self_to_checksumdata(context, &self, &data); + if (ret) { + free(self.auth); + goto out; + } + + ret = krb5_crypto_init(context, &krbtgt->session, 0, &crypto); + if (ret) { + free(self.auth); + krb5_data_free(&data); + goto out; + } + + ret = krb5_create_checksum(context, + crypto, + KRB5_KU_TGS_IMPERSONATE, + 0, + data.data, + data.length, + &self.cksum); + krb5_crypto_destroy(context, crypto); + krb5_data_free(&data); + if (ret) { + free(self.auth); + goto out; + } + + ASN1_MALLOC_ENCODE(PA_S4U2Self, buf, len, &self, &size, ret); + free(self.auth); + free_Checksum(&self.cksum); + if (ret) + goto out; + if (len != size) + krb5_abortx(context, "internal asn1 error"); + + ret = krb5_padata_add(context, &padata, KRB5_PADATA_S4U2SELF, buf, len); + if (ret) + goto out; } ret = init_tgs_req (context, id, addresses, flags, - flags.b.enc_tkt_in_skey ? &second_ticket : NULL, + second_ticket, in_creds, krbtgt, nonce, + &padata, &subkey, &req, usage); - if(flags.b.enc_tkt_in_skey) - free_Ticket(&second_ticket); if (ret) goto out; @@ -475,7 +543,7 @@ again: &krbtgt->addresses, nonce, TRUE, - flags.b.request_anonymous, + TRUE /* flags.b.request_anonymous */, decrypt_tkt_with_subkey, subkey); krb5_free_kdc_rep(context, &rep); @@ -497,6 +565,9 @@ again: } out: + if (second_ticket == &second_ticket_data) + free_Ticket(&second_ticket_data); + free_METHOD_DATA(&padata); krb5_data_free(&resp); krb5_data_free(&enc); if(subkey){ @@ -514,16 +585,20 @@ get_cred_kdc(krb5_context context, krb5_addresses *addresses, krb5_creds *in_creds, krb5_creds *krbtgt, + krb5_principal impersonate_principal, + Ticket *second_ticket, krb5_creds *out_creds) { krb5_error_code ret; ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds, - krbtgt, out_creds, KRB5_KU_TGS_REQ_AUTH); + krbtgt, impersonate_principal, second_ticket, + out_creds, KRB5_KU_TGS_REQ_AUTH); if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { krb5_clear_error_string (context); ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds, - krbtgt, out_creds, KRB5_KU_AP_REQ_AUTH); + krbtgt, impersonate_principal, second_ticket, + out_creds, KRB5_KU_AP_REQ_AUTH); } return ret; } @@ -533,6 +608,7 @@ get_cred_kdc(krb5_context context, static krb5_error_code get_cred_kdc_la(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, krb5_creds *in_creds, krb5_creds *krbtgt, + krb5_principal impersonate_principal, Ticket *second_ticket, krb5_creds *out_creds) { krb5_error_code ret; @@ -543,7 +619,8 @@ get_cred_kdc_la(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, if(addresses.len == 0) addrs = NULL; ret = get_cred_kdc(context, id, flags, addrs, - in_creds, krbtgt, out_creds); + in_creds, krbtgt, impersonate_principal, second_ticket, + out_creds); krb5_free_addresses(context, &addresses); return ret; } @@ -575,7 +652,7 @@ krb5_get_kdc_cred(krb5_context context, return ret; } ret = get_cred_kdc(context, id, flags, addresses, - in_creds, krbtgt, *out_creds); + in_creds, krbtgt, NULL, NULL, *out_creds); krb5_free_creds (context, krbtgt); if(ret) free(*out_creds); @@ -607,7 +684,17 @@ find_cred(krb5_context context, } tgts++; } - krb5_clear_error_string(context); + { + char *str; + ret = krb5_unparse_name(context, server, &str); + if(ret == 0) { + krb5_set_error_string(context, "Matching credential " + "(%s) not found", str); + free(str); + } else { + krb5_clear_error_string(context); + } + } return KRB5_CC_NOTFOUND; } @@ -650,6 +737,8 @@ get_cred_from_kdc_flags(krb5_context context, krb5_kdc_flags flags, krb5_ccache ccache, krb5_creds *in_creds, + krb5_principal impersonate_principal, + Ticket *second_ticket, krb5_creds **out_creds, krb5_creds ***ret_tgts) { @@ -707,10 +796,16 @@ get_cred_from_kdc_flags(krb5_context context, if (noaddr) ret = get_cred_kdc(context, ccache, flags, NULL, - in_creds, &tgts, *out_creds); + in_creds, &tgts, + impersonate_principal, + second_ticket, + *out_creds); else ret = get_cred_kdc_la(context, ccache, flags, - in_creds, &tgts, *out_creds); + in_creds, &tgts, + impersonate_principal, + second_ticket, + *out_creds); if (ret) { free (*out_creds); *out_creds = NULL; @@ -731,7 +826,7 @@ get_cred_from_kdc_flags(krb5_context context, heim_general_string tgt_inst; ret = get_cred_from_kdc_flags(context, flags, ccache, &tmp_creds, - &tgt, ret_tgts); + NULL, NULL, &tgt, ret_tgts); if(ret) { krb5_free_principal(context, tmp_creds.server); krb5_free_principal(context, tmp_creds.client); @@ -776,10 +871,12 @@ get_cred_from_kdc_flags(krb5_context context, &noaddr); if (noaddr) ret = get_cred_kdc (context, ccache, flags, NULL, - in_creds, tgt, *out_creds); + in_creds, tgt, NULL, NULL, + *out_creds); else ret = get_cred_kdc_la(context, ccache, flags, - in_creds, tgt, *out_creds); + in_creds, tgt, NULL, NULL, + *out_creds); if (ret) { free (*out_creds); *out_creds = NULL; @@ -800,7 +897,8 @@ krb5_get_cred_from_kdc_opt(krb5_context context, krb5_kdc_flags f; f.i = flags; return get_cred_from_kdc_flags(context, f, ccache, - in_creds, out_creds, ret_tgts); + in_creds, NULL, NULL, + out_creds, ret_tgts); } krb5_error_code KRB5_LIB_FUNCTION @@ -879,15 +977,18 @@ krb5_get_credentials_with_flags(krb5_context context, } if(options & KRB5_GC_USER_USER) flags.b.enc_tkt_in_skey = 1; + if (flags.b.enc_tkt_in_skey) + options |= KRB5_GC_NO_STORE; + tgts = NULL; ret = get_cred_from_kdc_flags(context, flags, ccache, - in_creds, out_creds, &tgts); + in_creds, NULL, NULL, out_creds, &tgts); for(i = 0; tgts && tgts[i]; i++) { krb5_cc_store_cred(context, ccache, tgts[i]); krb5_free_creds(context, tgts[i]); } free(tgts); - if(ret == 0 && flags.b.enc_tkt_in_skey == 0) + if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) krb5_cc_store_cred(context, ccache, *out_creds); return ret; } @@ -904,3 +1005,200 @@ krb5_get_credentials(krb5_context context, return krb5_get_credentials_with_flags(context, options, flags, ccache, in_creds, out_creds); } + +struct krb5_get_creds_opt_data { + krb5_principal self; + krb5_flags options; + krb5_enctype enctype; + Ticket *ticket; +}; + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_alloc(krb5_context context, krb5_get_creds_opt *opt) +{ + *opt = calloc(1, sizeof(**opt)); + if (*opt == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_free(krb5_context context, krb5_get_creds_opt opt) +{ + if (opt->self) + krb5_free_principal(context, opt->self); + memset(opt, 0, sizeof(*opt)); + free(opt); +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_options(krb5_context context, + krb5_get_creds_opt opt, + krb5_flags options) +{ + opt->options = options; +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_add_options(krb5_context context, + krb5_get_creds_opt opt, + krb5_flags options) +{ + opt->options |= options; +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_enctype(krb5_context context, + krb5_get_creds_opt opt, + krb5_enctype enctype) +{ + opt->enctype = enctype; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_impersonate(krb5_context context, + krb5_get_creds_opt opt, + krb5_const_principal self) +{ + if (opt->self) + krb5_free_principal(context, opt->self); + return krb5_copy_principal(context, self, &opt->self); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_ticket(krb5_context context, + krb5_get_creds_opt opt, + const Ticket *ticket) +{ + if (opt->ticket) { + free_Ticket(opt->ticket); + free(opt->ticket); + opt->ticket = NULL; + } + if (ticket) { + krb5_error_code ret; + + opt->ticket = malloc(sizeof(*ticket)); + if (opt->ticket == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = copy_Ticket(ticket, opt->ticket); + if (ret) { + free(opt->ticket); + opt->ticket = NULL; + krb5_set_error_string(context, "malloc: out of memory"); + return ret; + } + } + return 0; +} + + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds(krb5_context context, + krb5_get_creds_opt opt, + krb5_ccache ccache, + krb5_const_principal inprinc, + krb5_creds **out_creds) +{ + krb5_kdc_flags flags; + krb5_flags options; + krb5_creds in_creds; + krb5_error_code ret; + krb5_creds **tgts; + krb5_creds *res_creds; + int i; + + memset(&in_creds, 0, sizeof(in_creds)); + in_creds.server = rk_UNCONST(inprinc); + + ret = krb5_cc_get_principal(context, ccache, &in_creds.client); + if (ret) + return ret; + + options = opt->options; + flags.i = 0; + + *out_creds = NULL; + res_creds = calloc(1, sizeof(*res_creds)); + if (res_creds == NULL) { + krb5_free_principal(context, in_creds.client); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + if (opt->enctype) { + in_creds.session.keytype = opt->enctype; + options |= KRB5_TC_MATCH_KEYTYPE; + } + + /* + * If we got a credential, check if credential is expired before + * returning it. + */ + ret = krb5_cc_retrieve_cred(context, + ccache, + opt->enctype ? KRB5_TC_MATCH_KEYTYPE : 0, + &in_creds, res_creds); + /* + * If we got a credential, check if credential is expired before + * returning it, but only if KRB5_GC_EXPIRED_OK is not set. + */ + if (ret == 0) { + krb5_timestamp timeret; + + /* If expired ok, don't bother checking */ + if(options & KRB5_GC_EXPIRED_OK) { + *out_creds = res_creds; + krb5_free_principal(context, in_creds.client); + return 0; + } + + krb5_timeofday(context, &timeret); + if(res_creds->times.endtime > timeret) { + *out_creds = res_creds; + krb5_free_principal(context, in_creds.client); + return 0; + } + if(options & KRB5_GC_CACHED) + krb5_cc_remove_cred(context, ccache, 0, res_creds); + + } else if(ret != KRB5_CC_END) { + free(res_creds); + krb5_free_principal(context, in_creds.client); + return ret; + } + free(res_creds); + if(options & KRB5_GC_CACHED) { + krb5_clear_error_string (context); + krb5_free_principal(context, in_creds.client); + return KRB5_CC_NOTFOUND; + } + if(options & KRB5_GC_USER_USER) { + flags.b.enc_tkt_in_skey = 1; + options |= KRB5_GC_NO_STORE; + } + if (options & KRB5_GC_FORWARDABLE) + flags.b.forwardable = 1; + if (options & KRB5_GC_NO_TRANSIT_CHECK) + flags.b.disable_transited_check = 1; + + tgts = NULL; + ret = get_cred_from_kdc_flags(context, flags, ccache, + &in_creds, opt->self, opt->ticket, + out_creds, &tgts); + krb5_free_principal(context, in_creds.client); + for(i = 0; tgts && tgts[i]; i++) { + krb5_cc_store_cred(context, ccache, tgts[i]); + krb5_free_creds(context, tgts[i]); + } + free(tgts); + if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) + krb5_cc_store_cred(context, ccache, *out_creds); + return ret; +} diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index f042cdb573..661d05663b 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -376,7 +376,7 @@ krb5_get_forwarded_creds (krb5_context context, cred.enc_part.cipher.length = buf_size; } else { /* - * Here older versions than 0.7.2 of Heimdal used the local or + * Here older versions then 0.7.2 of Heimdal used the local or * remote subkey. That is wrong, the session key should be * used. Heimdal 0.7.2 and newer have code to try both in the * receiving end. diff --git a/source4/heimdal/lib/krb5/get_host_realm.c b/source4/heimdal/lib/krb5/get_host_realm.c index 33a3438b12..ffc646d98b 100644 --- a/source4/heimdal/lib/krb5/get_host_realm.c +++ b/source4/heimdal/lib/krb5/get_host_realm.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include <resolve.h> -RCSID("$Id: get_host_realm.c,v 1.35 2005/08/23 08:14:02 lha Exp $"); +RCSID("$Id: get_host_realm.c,v 1.37 2006/10/17 19:28:36 lha Exp $"); /* To automagically find the correct realm of a host (without * [domain_realm] in krb5.conf) add a text record for your domain with @@ -187,65 +187,71 @@ _krb5_get_host_realm_int (krb5_context context, return 0; } } - - *realms = malloc(2 * sizeof(krb5_realm)); - if (*realms == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - - (*realms)[1] = NULL; - p = strchr(host, '.'); if(p != NULL) { p++; - (*realms)[0] = strdup(p); - if((*realms)[0] == NULL) { - free(*realms); + *realms = malloc(2 * sizeof(krb5_realm)); + if (*realms == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - strupr((*realms)[0]); - } else { - krb5_error_code ret; - ret = krb5_get_default_realm(context, &(*realms)[0]); - if(ret) { + + (*realms)[0] = strdup(p); + if((*realms)[0] == NULL) { free(*realms); krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - if((*realms)[0] == NULL) { - free(*realms); - krb5_set_error_string(context, "unable to find realm of host %s", host); - return KRB5_ERR_HOST_REALM_UNKNOWN; - } + strupr((*realms)[0]); + (*realms)[1] = NULL; + return 0; } - return 0; + krb5_set_error_string(context, "unable to find realm of host %s", host); + return KRB5_ERR_HOST_REALM_UNKNOWN; } /* - * Return the realm(s) of `host' as a NULL-terminated list in `realms'. + * Return the realm(s) of `host' as a NULL-terminated list in + * `realms'. Free `realms' with krb5_free_host_realm(). */ krb5_error_code KRB5_LIB_FUNCTION krb5_get_host_realm(krb5_context context, - const char *host, + const char *targethost, krb5_realm **realms) { + const char *host = targethost; char hostname[MAXHOSTNAMELEN]; - krb5_boolean use_dns; + krb5_error_code ret; + int use_dns; if (host == NULL) { - if (gethostname (hostname, sizeof(hostname))) + if (gethostname (hostname, sizeof(hostname))) { + *realms = NULL; return errno; + } host = hostname; } - if (strchr(host, '.') == NULL) { - use_dns = FALSE; - } else { - use_dns = TRUE; - } + /* + * If our local hostname is without components, don't even try to dns. + */ + + use_dns = (strchr(host, '.') != NULL); - return _krb5_get_host_realm_int (context, host, use_dns, realms); + ret = _krb5_get_host_realm_int (context, host, use_dns, realms); + if (ret && targethost != NULL) { + /* + * If there was no realm mapping for the host (and we wasn't + * looking for ourself), guess at the local realm, maybe our + * KDC knows better then we do and we get a referral back. + */ + ret = krb5_get_default_realms(context, realms); + if (ret) { + krb5_set_error_string(context, "Unable to find realm of host %s", + host); + return KRB5_ERR_HOST_REALM_UNKNOWN; + } + } + return ret; } diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c index 5c488d1ddc..ebc96f2279 100644 --- a/source4/heimdal/lib/krb5/get_in_tkt.c +++ b/source4/heimdal/lib/krb5/get_in_tkt.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_in_tkt.c,v 1.116 2005/06/15 02:53:20 lha Exp $"); +RCSID("$Id: get_in_tkt.c,v 1.119 2006/10/06 17:05:08 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_init_etype (krb5_context context, @@ -137,7 +137,7 @@ _krb5_extract_ticket(krb5_context context, time_t tmp_time; krb5_timestamp sec_now; - ret = _krb5_principalname2krb5_principal (context, + ret = _krb5_principalname2krb5_principal (context, &tmp_principal, rep->kdc_rep.cname, rep->kdc_rep.crealm); @@ -171,7 +171,7 @@ _krb5_extract_ticket(krb5_context context, /* compare server */ - ret = _krb5_principalname2krb5_principal (context, + ret = _krb5_principalname2krb5_principal (context, &tmp_principal, rep->kdc_rep.ticket.sname, rep->kdc_rep.ticket.realm); @@ -411,7 +411,7 @@ add_padata(krb5_context context, static krb5_error_code init_as_req (krb5_context context, - krb5_kdc_flags opts, + KDCOptions opts, krb5_creds *creds, const krb5_addresses *addrs, const krb5_enctype *etypes, @@ -429,7 +429,7 @@ init_as_req (krb5_context context, a->pvno = 5; a->msg_type = krb_as_req; - a->req_body.kdc_options = opts.b; + a->req_body.kdc_options = opts; a->req_body.cname = malloc(sizeof(*a->req_body.cname)); if (a->req_body.cname == NULL) { ret = ENOMEM; @@ -649,14 +649,14 @@ krb5_get_in_cred(krb5_context context, krb5_salt salt; krb5_keyblock *key; size_t size; - krb5_kdc_flags opts; + KDCOptions opts; PA_DATA *pa; krb5_enctype etype; krb5_preauthdata *my_preauth = NULL; unsigned nonce; int done; - opts.i = options; + opts = int2KDCOptions(options); krb5_generate_random_block (&nonce, sizeof(nonce)); nonce &= 0xffffffff; @@ -771,7 +771,7 @@ krb5_get_in_cred(krb5_context context, NULL, nonce, FALSE, - opts.b.request_anonymous, + opts.request_anonymous, decrypt_proc, decryptarg); memset (key->keyvalue.data, 0, key->keyvalue.length); @@ -801,12 +801,9 @@ krb5_get_in_tkt(krb5_context context, krb5_kdc_rep *ret_as_reply) { krb5_error_code ret; - krb5_kdc_flags opts; - opts.i = 0; - opts.b = int2KDCOptions(options); ret = krb5_get_in_cred (context, - opts.i, + options, addrs, etypes, ptypes, diff --git a/source4/heimdal/lib/krb5/heim_err.c b/source4/heimdal/lib/krb5/heim_err.c new file mode 100644 index 0000000000..f72a265ba9 --- /dev/null +++ b/source4/heimdal/lib/krb5/heim_err.c @@ -0,0 +1,162 @@ +/* Generated from heim_err.et */ +/* $Id: heim_err.et,v 1.13 2004/02/13 16:23:40 lha Exp $ */ + +#include <stddef.h> +#include <com_err.h> +#include "heim_err.h" + +static const char *heim_error_strings[] = { + /* 000 */ "Error parsing log destination", + /* 001 */ "Failed to convert v4 principal", + /* 002 */ "Salt type is not supported by enctype", + /* 003 */ "Host not found", + /* 004 */ "Operation not supported", + /* 005 */ "End of file", + /* 006 */ "Failed to get the master key", + /* 007 */ "Unacceptable service used", + /* 008 */ "Reserved heim error (8)", + /* 009 */ "Reserved heim error (9)", + /* 010 */ "Reserved heim error (10)", + /* 011 */ "Reserved heim error (11)", + /* 012 */ "Reserved heim error (12)", + /* 013 */ "Reserved heim error (13)", + /* 014 */ "Reserved heim error (14)", + /* 015 */ "Reserved heim error (15)", + /* 016 */ "Reserved heim error (16)", + /* 017 */ "Reserved heim error (17)", + /* 018 */ "Reserved heim error (18)", + /* 019 */ "Reserved heim error (19)", + /* 020 */ "Reserved heim error (20)", + /* 021 */ "Reserved heim error (21)", + /* 022 */ "Reserved heim error (22)", + /* 023 */ "Reserved heim error (23)", + /* 024 */ "Reserved heim error (24)", + /* 025 */ "Reserved heim error (25)", + /* 026 */ "Reserved heim error (26)", + /* 027 */ "Reserved heim error (27)", + /* 028 */ "Reserved heim error (28)", + /* 029 */ "Reserved heim error (29)", + /* 030 */ "Reserved heim error (30)", + /* 031 */ "Reserved heim error (31)", + /* 032 */ "Reserved heim error (32)", + /* 033 */ "Reserved heim error (33)", + /* 034 */ "Reserved heim error (34)", + /* 035 */ "Reserved heim error (35)", + /* 036 */ "Reserved heim error (36)", + /* 037 */ "Reserved heim error (37)", + /* 038 */ "Reserved heim error (38)", + /* 039 */ "Reserved heim error (39)", + /* 040 */ "Reserved heim error (40)", + /* 041 */ "Reserved heim error (41)", + /* 042 */ "Reserved heim error (42)", + /* 043 */ "Reserved heim error (43)", + /* 044 */ "Reserved heim error (44)", + /* 045 */ "Reserved heim error (45)", + /* 046 */ "Reserved heim error (46)", + /* 047 */ "Reserved heim error (47)", + /* 048 */ "Reserved heim error (48)", + /* 049 */ "Reserved heim error (49)", + /* 050 */ "Reserved heim error (50)", + /* 051 */ "Reserved heim error (51)", + /* 052 */ "Reserved heim error (52)", + /* 053 */ "Reserved heim error (53)", + /* 054 */ "Reserved heim error (54)", + /* 055 */ "Reserved heim error (55)", + /* 056 */ "Reserved heim error (56)", + /* 057 */ "Reserved heim error (57)", + /* 058 */ "Reserved heim error (58)", + /* 059 */ "Reserved heim error (59)", + /* 060 */ "Reserved heim error (60)", + /* 061 */ "Reserved heim error (61)", + /* 062 */ "Reserved heim error (62)", + /* 063 */ "Reserved heim error (63)", + /* 064 */ "Certificate missing", + /* 065 */ "Private key missing", + /* 066 */ "No valid certificate authority", + /* 067 */ "Certificate invalid", + /* 068 */ "Private key invalid", + /* 069 */ "Reserved heim error (69)", + /* 070 */ "Reserved heim error (70)", + /* 071 */ "Reserved heim error (71)", + /* 072 */ "Reserved heim error (72)", + /* 073 */ "Reserved heim error (73)", + /* 074 */ "Reserved heim error (74)", + /* 075 */ "Reserved heim error (75)", + /* 076 */ "Reserved heim error (76)", + /* 077 */ "Reserved heim error (77)", + /* 078 */ "Reserved heim error (78)", + /* 079 */ "Reserved heim error (79)", + /* 080 */ "Reserved heim error (80)", + /* 081 */ "Reserved heim error (81)", + /* 082 */ "Reserved heim error (82)", + /* 083 */ "Reserved heim error (83)", + /* 084 */ "Reserved heim error (84)", + /* 085 */ "Reserved heim error (85)", + /* 086 */ "Reserved heim error (86)", + /* 087 */ "Reserved heim error (87)", + /* 088 */ "Reserved heim error (88)", + /* 089 */ "Reserved heim error (89)", + /* 090 */ "Reserved heim error (90)", + /* 091 */ "Reserved heim error (91)", + /* 092 */ "Reserved heim error (92)", + /* 093 */ "Reserved heim error (93)", + /* 094 */ "Reserved heim error (94)", + /* 095 */ "Reserved heim error (95)", + /* 096 */ "Reserved heim error (96)", + /* 097 */ "Reserved heim error (97)", + /* 098 */ "Reserved heim error (98)", + /* 099 */ "Reserved heim error (99)", + /* 100 */ "Reserved heim error (100)", + /* 101 */ "Reserved heim error (101)", + /* 102 */ "Reserved heim error (102)", + /* 103 */ "Reserved heim error (103)", + /* 104 */ "Reserved heim error (104)", + /* 105 */ "Reserved heim error (105)", + /* 106 */ "Reserved heim error (106)", + /* 107 */ "Reserved heim error (107)", + /* 108 */ "Reserved heim error (108)", + /* 109 */ "Reserved heim error (109)", + /* 110 */ "Reserved heim error (110)", + /* 111 */ "Reserved heim error (111)", + /* 112 */ "Reserved heim error (112)", + /* 113 */ "Reserved heim error (113)", + /* 114 */ "Reserved heim error (114)", + /* 115 */ "Reserved heim error (115)", + /* 116 */ "Reserved heim error (116)", + /* 117 */ "Reserved heim error (117)", + /* 118 */ "Reserved heim error (118)", + /* 119 */ "Reserved heim error (119)", + /* 120 */ "Reserved heim error (120)", + /* 121 */ "Reserved heim error (121)", + /* 122 */ "Reserved heim error (122)", + /* 123 */ "Reserved heim error (123)", + /* 124 */ "Reserved heim error (124)", + /* 125 */ "Reserved heim error (125)", + /* 126 */ "Reserved heim error (126)", + /* 127 */ "Reserved heim error (127)", + /* 128 */ "unknown error from getaddrinfo", + /* 129 */ "address family for nodename not supported", + /* 130 */ "temporary failure in name resolution", + /* 131 */ "invalid value for ai_flags", + /* 132 */ "non-recoverable failure in name resolution", + /* 133 */ "ai_family not supported", + /* 134 */ "memory allocation failure", + /* 135 */ "no address associated with nodename", + /* 136 */ "nodename nor servname provided, or not known", + /* 137 */ "servname not supported for ai_socktype", + /* 138 */ "ai_socktype not supported", + /* 139 */ "system error returned in errno", + NULL +}; + +#define num_errors 140 + +void initialize_heim_error_table_r(struct et_list **list) +{ + initialize_error_table_r(list, heim_error_strings, num_errors, ERROR_TABLE_BASE_heim); +} + +void initialize_heim_error_table(void) +{ + init_error_table(heim_error_strings, ERROR_TABLE_BASE_heim, num_errors); +} diff --git a/source4/heimdal/lib/krb5/heim_threads.h b/source4/heimdal/lib/krb5/heim_threads.h index 41f0f83306..3ebe66beee 100755 --- a/source4/heimdal/lib/krb5/heim_threads.h +++ b/source4/heimdal/lib/krb5/heim_threads.h @@ -53,7 +53,7 @@ /* * NetBSD have a thread lib that we can use that part of libc that * works regardless if application are linked to pthreads or not. - * NetBSD newer than 2.99.11 just use pthread.h, and the same thing + * NetBSD newer then 2.99.11 just use pthread.h, and the same thing * will happen. */ #include <threadlib.h> diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index 88de280a00..6dacb316d8 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c,v 1.23 2006/04/02 01:08:30 lha Exp $"); +RCSID("$Id: init_creds.c,v 1.28 2006/09/04 14:28:54 lha Exp $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) @@ -97,6 +97,39 @@ _krb5_get_init_creds_opt_copy(krb5_context context, } void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_free_krb5_error(krb5_get_init_creds_opt *opt) +{ + if (opt->opt_private == NULL || opt->opt_private->error == NULL) + return; + free_KRB_ERROR(opt->opt_private->error); + free(opt->opt_private->error); + opt->opt_private->error = NULL; +} + +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_set_krb5_error(krb5_context context, + krb5_get_init_creds_opt *opt, + const KRB_ERROR *error) +{ + krb5_error_code ret; + + if (opt->opt_private == NULL) + return; + + _krb5_get_init_creds_opt_free_krb5_error(opt); + + opt->opt_private->error = malloc(sizeof(*opt->opt_private->error)); + if (opt->opt_private->error == NULL) + return; + ret = copy_KRB_ERROR(error, opt->opt_private->error); + if (ret) { + free(opt->opt_private->error); + opt->opt_private->error = NULL; + } +} + + +void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt) { if (opt->opt_private == NULL) @@ -104,6 +137,7 @@ krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt) if (opt->opt_private->refcount < 1) /* abort ? */ return; if (--opt->opt_private->refcount == 0) { + _krb5_get_init_creds_opt_free_krb5_error(opt); _krb5_get_init_creds_opt_free_pkinit(opt); free(opt->opt_private); } @@ -160,8 +194,6 @@ get_config_bool (krb5_context context, * [realms] or [libdefaults] for some of the values. */ -static krb5_addresses no_addrs = {0, NULL}; - void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_set_default_flags(krb5_context context, const char *appname, @@ -192,9 +224,9 @@ krb5_get_init_creds_opt_set_default_flags(krb5_context context, krb5_get_init_creds_opt_set_renew_life(opt, t); krb5_appdefault_boolean(context, appname, realm, "no-addresses", - KRB5_ADDRESSLESS_DEFAULT, &b); + FALSE, &b); if (b) - krb5_get_init_creds_opt_set_address_list (opt, &no_addrs); + krb5_get_init_creds_opt_set_addressless (context, opt, TRUE); #if 0 krb5_appdefault_boolean(context, appname, realm, "anonymous", FALSE, &b); @@ -326,7 +358,52 @@ krb5_get_init_creds_opt_set_pac_request(krb5_context context, if (ret) return ret; opt->opt_private->req_pac = req_pac ? - KRB5_PA_PAC_REQ_TRUE : - KRB5_PA_PAC_REQ_FALSE; + KRB5_INIT_CREDS_TRISTATE_TRUE : + KRB5_INIT_CREDS_TRISTATE_FALSE; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_get_error(krb5_context context, + krb5_get_init_creds_opt *opt, + KRB_ERROR **error) +{ + krb5_error_code ret; + + *error = NULL; + + ret = require_ext_opt(context, opt, "init_creds_opt_get_error"); + if (ret) + return ret; + + if (opt->opt_private->error == NULL) + return 0; + + *error = malloc(sizeof(**error)); + if (*error == NULL) { + krb5_set_error_string(context, "malloc - out memory"); + return ENOMEM; + } + + ret = copy_KRB_ERROR(*error, opt->opt_private->error); + if (ret) + krb5_clear_error_string(context); + + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_addressless(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_boolean addressless) +{ + krb5_error_code ret; + ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); + if (ret) + return ret; + if (addressless) + opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_TRUE; + else + opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_FALSE; return 0; } diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index c05386ec23..d43ae0ae6f 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,10 +33,10 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c,v 1.94 2006/04/24 08:49:08 lha Exp $"); +RCSID("$Id: init_creds_pw.c,v 1.101 2006/10/02 12:00:59 lha Exp $"); typedef struct krb5_get_init_creds_ctx { - krb5_kdc_flags flags; + KDCOptions flags; krb5_creds cred; krb5_addresses *addrs; krb5_enctype *etypes; @@ -52,7 +52,7 @@ typedef struct krb5_get_init_creds_ctx { const char *password; krb5_s2k_proc key_proc; - krb5_get_init_creds_req_pac req_pac; + krb5_get_init_creds_tristate req_pac; krb5_pk_init_ctx pk_init_ctx; } krb5_get_init_creds_ctx; @@ -256,9 +256,10 @@ print_expire (krb5_context context, } } +static krb5_addresses no_addrs = { 0, NULL }; + static krb5_error_code get_init_creds_common(krb5_context context, - krb5_creds *creds, krb5_principal client, krb5_deltat start_time, const char *in_tkt_service, @@ -275,6 +276,8 @@ get_init_creds_common(krb5_context context, if (options == NULL) { krb5_get_init_creds_opt_init (&default_opt); options = &default_opt; + } else { + _krb5_get_init_creds_opt_free_krb5_error(options); } if (options->opt_private) { @@ -283,13 +286,12 @@ get_init_creds_common(krb5_context context, ctx->req_pac = options->opt_private->req_pac; ctx->pk_init_ctx = options->opt_private->pk_init_ctx; } else - ctx->req_pac = KRB5_PA_PAC_DONT_CARE; + ctx->req_pac = KRB5_INIT_CREDS_TRISTATE_UNSET; if (ctx->key_proc == NULL) ctx->key_proc = default_s2k_func; ctx->pre_auth_types = NULL; - ctx->flags.i = 0; ctx->addrs = NULL; ctx->etypes = NULL; ctx->pre_auth_types = NULL; @@ -300,20 +302,35 @@ get_init_creds_common(krb5_context context, if (ret) return ret; - ctx->flags.i = 0; - if (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE) - ctx->flags.b.forwardable = options->forwardable; + ctx->flags.forwardable = options->forwardable; if (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE) - ctx->flags.b.proxiable = options->proxiable; + ctx->flags.proxiable = options->proxiable; if (start_time) - ctx->flags.b.postdated = 1; + ctx->flags.postdated = 1; if (ctx->cred.times.renew_till) - ctx->flags.b.renewable = 1; - if (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) + ctx->flags.renewable = 1; + if (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) { ctx->addrs = options->address_list; + } else if (options->opt_private) { + switch (options->opt_private->addressless) { + case KRB5_INIT_CREDS_TRISTATE_UNSET: +#if KRB5_ADDRESSLESS_DEFAULT == TRUE + ctx->addrs = &no_addrs; +#else + ctx->addrs = NULL; +#endif + break; + case KRB5_INIT_CREDS_TRISTATE_FALSE: + ctx->addrs = NULL; + break; + case KRB5_INIT_CREDS_TRISTATE_TRUE: + ctx->addrs = &no_addrs; + break; + } + } if (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) { etypes = malloc((options->etype_list_length + 1) * sizeof(krb5_enctype)); @@ -341,7 +358,7 @@ get_init_creds_common(krb5_context context, if (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT) ; /* XXX */ if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS) - ctx->flags.b.request_anonymous = options->anonymous; + ctx->flags.request_anonymous = options->anonymous; return 0; } @@ -478,7 +495,7 @@ krb5_get_init_creds_keytab(krb5_context context, krb5_error_code ret; krb5_keytab_key_proc_args *a; - ret = get_init_creds_common(context, creds, client, start_time, + ret = get_init_creds_common(context, client, start_time, in_tkt_service, options, &ctx); if (ret) goto out; @@ -493,7 +510,7 @@ krb5_get_init_creds_keytab(krb5_context context, a->keytab = keytab; ret = krb5_get_in_cred (context, - ctx.flags.i, + KDCOptions2int(ctx.flags), ctx.addrs, ctx.etypes, ctx.pre_auth_types, @@ -522,7 +539,7 @@ krb5_get_init_creds_keytab(krb5_context context, static krb5_error_code init_creds_init_as_req (krb5_context context, - krb5_kdc_flags opts, + KDCOptions opts, const krb5_creds *creds, const krb5_addresses *addrs, const krb5_enctype *etypes, @@ -534,7 +551,7 @@ init_creds_init_as_req (krb5_context context, a->pvno = 5; a->msg_type = krb_as_req; - a->req_body.kdc_options = opts.b; + a->req_body.kdc_options = opts; a->req_body.cname = malloc(sizeof(*a->req_body.cname)); if (a->req_body.cname == NULL) { ret = ENOMEM; @@ -1028,12 +1045,12 @@ pa_data_add_pac_request(krb5_context context, void *buf; switch (ctx->req_pac) { - case KRB5_PA_PAC_DONT_CARE: + case KRB5_INIT_CREDS_TRISTATE_UNSET: return 0; /* don't bother */ - case KRB5_PA_PAC_REQ_TRUE: + case KRB5_INIT_CREDS_TRISTATE_TRUE: req.include_pac = 1; break; - case KRB5_PA_PAC_REQ_FALSE: + case KRB5_INIT_CREDS_TRISTATE_FALSE: req.include_pac = 0; } @@ -1176,7 +1193,7 @@ process_pa_data_to_key(krb5_context context, static krb5_error_code init_cred_loop(krb5_context context, - const krb5_get_init_creds_opt *init_cred_opts, + krb5_get_init_creds_opt *init_cred_opts, const krb5_prompter_fct prompter, void *prompter_data, krb5_get_init_creds_ctx *ctx, @@ -1196,6 +1213,8 @@ init_cred_loop(krb5_context context, memset(&md, 0, sizeof(md)); memset(&rep, 0, sizeof(rep)); + _krb5_get_init_creds_opt_free_krb5_error(init_cred_opts); + if (ret_as_reply) memset(ret_as_reply, 0, sizeof(*ret_as_reply)); @@ -1211,7 +1230,7 @@ init_cred_loop(krb5_context context, ctx->pk_nonce = ctx->nonce; /* - * Increase counter when we want other pre-auth types than + * Increase counter when we want other pre-auth types then * KRB5_PA_ENC_TIMESTAMP. */ #define MAX_PA_COUNTER 3 @@ -1306,6 +1325,9 @@ init_cred_loop(krb5_context context, krb5_free_error_contents(context, &error); send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; } else { + _krb5_get_init_creds_opt_set_krb5_error(context, + init_cred_opts, + &error); if (ret_as_reply) rep.error = error; else @@ -1332,7 +1354,7 @@ init_cred_loop(krb5_context context, NULL, ctx->nonce, FALSE, - ctx->flags.b.request_anonymous, + ctx->flags.request_anonymous, NULL, NULL); krb5_free_keyblock(context, key); @@ -1344,7 +1366,7 @@ out: if (ret == 0 && ret_as_reply) *ret_as_reply = rep; - else + else krb5_free_kdc_rep (context, &rep); return ret; } @@ -1367,7 +1389,7 @@ krb5_get_init_creds(krb5_context context, memset(&kdc_reply, 0, sizeof(kdc_reply)); - ret = get_init_creds_common(context, creds, client, start_time, + ret = get_init_creds_common(context, client, start_time, in_tkt_service, options, &ctx); if (ret) goto out; @@ -1391,7 +1413,7 @@ krb5_get_init_creds(krb5_context context, case KRB5KDC_ERR_KEY_EXPIRED : /* try to avoid recursion */ - /* don't try to change password where there where none */ + /* don't try to change password where then where none */ if (prompter == NULL || ctx.password == NULL) goto out; @@ -1528,13 +1550,13 @@ krb5_get_init_creds_keyblock(krb5_context context, struct krb5_get_init_creds_ctx ctx; krb5_error_code ret; - ret = get_init_creds_common(context, creds, client, start_time, + ret = get_init_creds_common(context, client, start_time, in_tkt_service, options, &ctx); if (ret) goto out; ret = krb5_get_in_cred (context, - ctx.flags.i, + KDCOptions2int(ctx.flags), ctx.addrs, ctx.etypes, ctx.pre_auth_types, diff --git a/source4/heimdal/lib/krb5/k524_err.c b/source4/heimdal/lib/krb5/k524_err.c new file mode 100644 index 0000000000..266d3ee577 --- /dev/null +++ b/source4/heimdal/lib/krb5/k524_err.c @@ -0,0 +1,30 @@ +/* Generated from k524_err.et */ +/* $Id: k524_err.et,v 1.1 2001/06/20 02:44:11 joda Exp $ */ + +#include <stddef.h> +#include <com_err.h> +#include "k524_err.h" + +static const char *k524_error_strings[] = { + /* 000 */ "wrong keytype in ticket", + /* 001 */ "incorrect network address", + /* 002 */ "cannot convert V5 principal", + /* 003 */ "V5 realm name longer than V4 maximum", + /* 004 */ "kerberos V4 error server", + /* 005 */ "encoding too large at server", + /* 006 */ "decoding out of data", + /* 007 */ "service not responding", + NULL +}; + +#define num_errors 8 + +void initialize_k524_error_table_r(struct et_list **list) +{ + initialize_error_table_r(list, k524_error_strings, num_errors, ERROR_TABLE_BASE_k524); +} + +void initialize_k524_error_table(void) +{ + init_error_table(k524_error_strings, ERROR_TABLE_BASE_k524, num_errors); +} diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 9ba288e22b..968b6079b7 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -17,7 +17,7 @@ _krb5_aes_cts_encrypt ( const unsigned char */*in*/, unsigned char */*out*/, size_t /*len*/, - const void */*aes_key*/, + const AES_KEY */*key*/, unsigned char */*ivec*/, const int /*encryptp*/); @@ -46,6 +46,12 @@ _krb5_dh_group_ok ( struct krb5_dh_moduli **/*moduli*/, char **/*name*/); +krb5_error_code KRB5_LIB_FUNCTION +_krb5_enctype_to_oid ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + heim_oid */*oid*/); + krb5_error_code _krb5_expand_default_cc_name ( krb5_context /*context*/, @@ -101,8 +107,17 @@ _krb5_get_init_creds_opt_copy ( krb5_get_init_creds_opt **/*out*/); void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_free_krb5_error (krb5_get_init_creds_opt */*opt*/); + +void KRB5_LIB_FUNCTION _krb5_get_init_creds_opt_free_pkinit (krb5_get_init_creds_opt */*opt*/); +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_set_krb5_error ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + const KRB_ERROR */*error*/); + krb5_ssize_t KRB5_LIB_FUNCTION _krb5_get_int ( void */*buffer*/, @@ -312,8 +327,8 @@ _krb5_pk_load_id ( struct krb5_pk_identity **/*ret_id*/, const char */*user_id*/, const char */*anchor_id*/, - char * const */*chain*/, - char * const */*revoke*/, + char * const */*chain_list*/, + char * const */*revoke_list*/, krb5_prompter_fct /*prompter*/, void */*prompter_data*/, char */*password*/); @@ -372,7 +387,7 @@ _krb5_principal2principalname ( krb5_error_code KRB5_LIB_FUNCTION _krb5_principalname2krb5_principal ( - krb5_context /* context */, + krb5_context /*context*/, krb5_principal */*principal*/, const PrincipalName /*from*/, const Realm /*realm*/); @@ -383,6 +398,12 @@ _krb5_put_int ( unsigned long /*value*/, size_t /*size*/); +krb5_error_code KRB5_LIB_FUNCTION +_krb5_s4u2self_to_checksumdata ( + krb5_context /*context*/, + const PA_S4U2Self */*self*/, + krb5_data */*data*/); + int _krb5_send_and_recv_tcp ( int /*fd*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 37293ff982..2010e25f5a 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -1066,13 +1066,6 @@ krb5_crypto_get_checksum_type ( krb5_cksumtype */*type*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_get_params ( - krb5_context /*context*/, - const krb5_crypto /*crypto*/, - const krb5_data */*params*/, - krb5_data */*ivec*/); - -krb5_error_code KRB5_LIB_FUNCTION krb5_crypto_getblocksize ( krb5_context /*context*/, krb5_crypto /*crypto*/, @@ -1104,13 +1097,6 @@ krb5_crypto_init ( krb5_crypto */*crypto*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_set_params ( - krb5_context /*context*/, - const krb5_crypto /*crypto*/, - const krb5_data */*ivec*/, - krb5_data */*params*/); - -krb5_error_code KRB5_LIB_FUNCTION krb5_data_alloc ( krb5_data */*p*/, int /*len*/); @@ -1246,6 +1232,169 @@ krb5_derive_key ( size_t /*constant_len*/, krb5_keyblock **/*derived_key*/); +krb5_error_code +krb5_digest_alloc ( + krb5_context /*context*/, + krb5_digest */*digest*/); + +void +krb5_digest_free (krb5_digest /*digest*/); + +krb5_error_code +krb5_digest_get_a1_hash ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_data */*data*/); + +krb5_error_code +krb5_digest_get_client_binding ( + krb5_context /*context*/, + krb5_digest /*digest*/, + char **/*type*/, + char **/*binding*/); + +const char * +krb5_digest_get_identifier ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +const char * +krb5_digest_get_opaque ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +const char * +krb5_digest_get_responseData ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +const char * +krb5_digest_get_rsp ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +const char * +krb5_digest_get_server_nonce ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +krb5_error_code +krb5_digest_get_tickets ( + krb5_context /*context*/, + krb5_digest /*digest*/, + Ticket **/*tickets*/); + +krb5_error_code +krb5_digest_init_request ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/); + +krb5_error_code +krb5_digest_request ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/); + +krb5_error_code +krb5_digest_set_authentication_user ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_principal /*authentication_user*/); + +krb5_error_code +krb5_digest_set_authid ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*authid*/); + +krb5_error_code +krb5_digest_set_client_nonce ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*nonce*/); + +krb5_error_code +krb5_digest_set_digest ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*dgst*/); + +krb5_error_code +krb5_digest_set_hostname ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*hostname*/); + +krb5_error_code +krb5_digest_set_identifier ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*id*/); + +krb5_error_code +krb5_digest_set_method ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*method*/); + +krb5_error_code +krb5_digest_set_nonceCount ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*nonce_count*/); + +krb5_error_code +krb5_digest_set_opaque ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*opaque*/); + +krb5_error_code +krb5_digest_set_qop ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*qop*/); + +krb5_error_code +krb5_digest_set_realm ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*realm*/); + +krb5_error_code +krb5_digest_set_server_cb ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*type*/, + const char */*binding*/); + +krb5_error_code +krb5_digest_set_server_nonce ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*nonce*/); + +krb5_error_code +krb5_digest_set_type ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*type*/); + +krb5_error_code +krb5_digest_set_uri ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*uri*/); + +krb5_error_code +krb5_digest_set_username ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*username*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_domain_x500_decode ( krb5_context /*context*/, @@ -1377,12 +1526,6 @@ krb5_enctype_to_keytype ( krb5_keytype */*keytype*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_enctype_to_oid ( - krb5_context /*context*/, - krb5_enctype /*etype*/, - heim_oid */*oid*/); - -krb5_error_code KRB5_LIB_FUNCTION krb5_enctype_to_string ( krb5_context /*context*/, krb5_enctype /*etype*/, @@ -1652,6 +1795,54 @@ krb5_get_credentials_with_flags ( krb5_creds **/*out_creds*/); krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_ccache /*ccache*/, + krb5_const_principal /*inprinc*/, + krb5_creds **/*out_creds*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_add_options ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_flags /*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_alloc ( + krb5_context /*context*/, + krb5_get_creds_opt */*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_free ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_enctype ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_enctype /*enctype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_impersonate ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_const_principal /*self*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_options ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_flags /*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_ticket ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + const Ticket */*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION krb5_get_default_config_files (char ***/*pfilenames*/); krb5_error_code KRB5_LIB_FUNCTION @@ -1674,6 +1865,9 @@ krb5_get_default_realms ( krb5_context /*context*/, krb5_realm **/*realms*/); +krb5_boolean KRB5_LIB_FUNCTION +krb5_get_dns_canonize_hostname (krb5_context /*context*/); + const char* KRB5_LIB_FUNCTION krb5_get_err_text ( krb5_context /*context*/, @@ -1710,7 +1904,7 @@ krb5_get_forwarded_creds ( krb5_error_code KRB5_LIB_FUNCTION krb5_get_host_realm ( krb5_context /*context*/, - const char */*host*/, + const char */*targethost*/, krb5_realm **/*realms*/); krb5_error_code KRB5_LIB_FUNCTION @@ -1823,6 +2017,12 @@ krb5_get_init_creds_opt_alloc ( void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_free (krb5_get_init_creds_opt */*opt*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_get_error ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + KRB_ERROR **/*error*/); + void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init (krb5_get_init_creds_opt */*opt*/); @@ -1831,6 +2031,12 @@ krb5_get_init_creds_opt_set_address_list ( krb5_get_init_creds_opt */*opt*/, krb5_addresses */*addresses*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_addressless ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + krb5_boolean /*addressless*/); + void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_set_anonymous ( krb5_get_init_creds_opt */*opt*/, @@ -1874,8 +2080,8 @@ krb5_get_init_creds_opt_set_pkinit ( krb5_principal /*principal*/, const char */*user_id*/, const char */*x509_anchors*/, - char * const * /*chain*/, - char * const * /*revoke*/, + char * const * /*pool*/, + char * const * /*pki_revoke*/, int /*flags*/, krb5_prompter_fct /*prompter*/, void */*prompter_data*/, @@ -1930,6 +2136,12 @@ krb5_get_kdc_cred ( krb5_creds **out_creds ); krb5_error_code KRB5_LIB_FUNCTION +krb5_get_kdc_sec_offset ( + krb5_context /*context*/, + int32_t */*sec*/, + int32_t */*usec*/); + +krb5_error_code KRB5_LIB_FUNCTION krb5_get_krb524hst ( krb5_context /*context*/, const krb5_realm */*realm*/, @@ -2035,6 +2247,9 @@ krb5_initlog ( krb5_boolean KRB5_LIB_FUNCTION krb5_is_thread_safe (void); +const krb5_enctype * KRB5_LIB_FUNCTION +krb5_kerberos_enctypes (krb5_context /*context*/); + krb5_enctype krb5_keyblock_get_enctype (const krb5_keyblock */*block*/); @@ -2412,15 +2627,10 @@ krb5_parse_name ( krb5_principal */*principal*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_name_mustrealm ( - krb5_context /*context*/, - const char */*name*/, - krb5_principal */*principal*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_name_norealm ( +krb5_parse_name_flags ( krb5_context /*context*/, const char */*name*/, + int /*flags*/, krb5_principal */*principal*/); const char* KRB5_LIB_FUNCTION @@ -2447,7 +2657,7 @@ krb5_prepend_config_files_default ( const char */*filelist*/, char ***/*pfilenames*/); -krb5_realm* KRB5_LIB_FUNCTION +krb5_realm * KRB5_LIB_FUNCTION krb5_princ_realm ( krb5_context /*context*/, krb5_principal /*principal*/); @@ -2793,6 +3003,11 @@ krb5_ret_string ( char **/*string*/); krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_stringnl ( + krb5_storage */*sp*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION krb5_ret_stringz ( krb5_storage */*sp*/, char **/*string*/); @@ -2877,6 +3092,11 @@ krb5_set_default_realm ( krb5_context /*context*/, const char */*realm*/); +void KRB5_LIB_FUNCTION +krb5_set_dns_canonicalize_hostname ( + krb5_context /*context*/, + krb5_boolean /*flag*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_set_error_string ( krb5_context /*context*/, @@ -2926,10 +3146,9 @@ krb5_set_real_time ( int32_t /*usec*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_set_send_recv_func ( +krb5_set_send_to_kdc_func ( krb5_context /*context*/, - krb5_send_and_recv_func_t /*func*/, - krb5_send_and_recv_close_func_t /*close_fn*/, + krb5_send_to_kdc_func /*func*/, void */*data*/); void KRB5_LIB_FUNCTION @@ -3110,6 +3329,11 @@ krb5_store_string ( const char */*s*/); krb5_error_code KRB5_LIB_FUNCTION +krb5_store_stringnl ( + krb5_storage */*sp*/, + const char */*s*/); + +krb5_error_code KRB5_LIB_FUNCTION krb5_store_stringz ( krb5_storage */*sp*/, const char */*s*/); @@ -3254,24 +3478,26 @@ krb5_unparse_name_fixed ( size_t /*len*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_fixed_short ( +krb5_unparse_name_fixed_flags ( krb5_context /*context*/, krb5_const_principal /*principal*/, + int /*flags*/, char */*name*/, size_t /*len*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_norealm ( +krb5_unparse_name_fixed_short ( krb5_context /*context*/, krb5_const_principal /*principal*/, - char **/*name*/); + char */*name*/, + size_t /*len*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_norealm_fixed ( +krb5_unparse_name_flags ( krb5_context /*context*/, krb5_const_principal /*principal*/, - char */*name*/, - size_t /*len*/); + int /*flags*/, + char **/*name*/); krb5_error_code KRB5_LIB_FUNCTION krb5_unparse_name_short ( diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 32fdd6d383..4b5058094b 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h,v 1.241 2006/05/05 09:29:36 lha Exp $ */ +/* $Id: krb5.h,v 1.253 2006/10/20 18:12:06 lha Exp $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -72,6 +72,12 @@ typedef const void *krb5_const_pointer; struct krb5_crypto_data; typedef struct krb5_crypto_data *krb5_crypto; +struct krb5_get_creds_opt_data; +typedef struct krb5_get_creds_opt_data *krb5_get_creds_opt; + +struct krb5_digest; +typedef struct krb5_digest *krb5_digest; + typedef CKSUMTYPE krb5_cksumtype; typedef Checksum krb5_checksum; @@ -203,8 +209,16 @@ typedef enum krb5_key_usage { /* Encryption of the SAM-TRACK-ID field */ KRB5_KU_PA_SERVER_REFERRAL = 26, /* Keyusage for the server referral in a TGS req */ - KRB5_KU_SAM_ENC_NONCE_SAD = 27 + KRB5_KU_SAM_ENC_NONCE_SAD = 27, /* Encryption of the SAM-NONCE-OR-SAD field */ + KRB5_KU_TGS_IMPERSONATE = -17, + /* Checksum type used in the impersonate field */ + KRB5_KU_DIGEST_ENCRYPT = -18, + /* Encryption key usage used in the digest encryption field */ + KRB5_KU_DIGEST_OPAQUE = -19, + /* Checksum key usage used in the digest opaque field */ + KRB5_KU_KRB5SIGNEDPATH = -21 + /* Checksum key usage on KRB5SignedPath */ } krb5_key_usage; typedef krb5_key_usage krb5_keyusage; @@ -256,9 +270,7 @@ typedef enum krb5_keytype { KEYTYPE_AES128 = 17, KEYTYPE_AES256 = 18, KEYTYPE_ARCFOUR = 23, - KEYTYPE_ARCFOUR_56 = 24, - KEYTYPE_RC2 = -0x1005, - KEYTYPE_AES192 = -0x1006 + KEYTYPE_ARCFOUR_56 = 24 } krb5_keytype; typedef EncryptionKey krb5_keyblock; @@ -339,6 +351,9 @@ typedef union { #define KRB5_GC_CACHED (1U << 0) #define KRB5_GC_USER_USER (1U << 1) #define KRB5_GC_EXPIRED_OK (1U << 2) +#define KRB5_GC_NO_STORE (1U << 3) +#define KRB5_GC_FORWARDABLE (1U << 4) +#define KRB5_GC_NO_TRANSIT_CHECK (1U << 5) /* constants for compare_creds (and cc_retrieve_cred) */ #define KRB5_TC_DONT_MATCH_REALM (1U << 31) @@ -413,49 +428,6 @@ typedef struct krb5_config_binding krb5_config_binding; typedef krb5_config_binding krb5_config_section; -typedef struct krb5_context_data { - krb5_enctype *etypes; - krb5_enctype *etypes_des; - char **default_realms; - time_t max_skew; - time_t kdc_timeout; - unsigned max_retries; - int32_t kdc_sec_offset; - int32_t kdc_usec_offset; - krb5_config_section *cf; - struct et_list *et_list; - struct krb5_log_facility *warn_dest; - krb5_cc_ops *cc_ops; - int num_cc_ops; - const char *http_proxy; - const char *time_fmt; - krb5_boolean log_utc; - const char *default_keytab; - const char *default_keytab_modify; - krb5_boolean use_admin_kdc; - krb5_addresses *extra_addresses; - krb5_boolean scan_interfaces; /* `ifconfig -a' */ - krb5_boolean srv_lookup; /* do SRV lookups */ - krb5_boolean srv_try_txt; /* try TXT records also */ - int32_t fcache_vno; /* create cache files w/ this - version */ - int num_kt_types; /* # of registered keytab types */ - struct krb5_keytab_data *kt_types; /* registered keytab types */ - const char *date_fmt; - char *error_string; - char error_buf[256]; - krb5_addresses *ignore_addresses; - char *default_cc_name; - int pkinit_flags; - void *mutex; /* protects error_string/error_buf */ - int large_msg_size; - krb5_boolean fdns; /* Lookup hostnames to find full name, or send as-is */ - struct send_and_recv *send_and_recv; /* Alternate functions for KDC communication */ - void *mem_ctx; /* Some parts of Samba4 need a valid - memory context (under the event - context) to use */ -} krb5_context_data; - enum { KRB5_PKINIT_WIN2K = 1, /* wire compatible with Windows 2k */ KRB5_PKINIT_PACKET_CABLE = 2 /* use packet cable standard */ @@ -578,8 +550,8 @@ typedef struct krb5_auth_context_data { krb5_rcache rcache; - krb5_keytype keytype; /* ¿requested key type ? */ - krb5_cksumtype cksumtype; /* ¡requested checksum type! */ + krb5_keytype keytype; /* ¿requested key type ? */ + krb5_cksumtype cksumtype; /* ¡requested checksum type! */ }krb5_auth_context_data, *krb5_auth_context; @@ -609,6 +581,8 @@ typedef EncAPRepPart krb5_ap_rep_enc_part; #define KRB5_TGS_NAME_SIZE (6) #define KRB5_TGS_NAME ("krbtgt") +#define KRB5_DIGEST_NAME ("digest") + /* variables */ extern const char *krb5_config_file; @@ -618,7 +592,8 @@ typedef enum { KRB5_PROMPT_TYPE_PASSWORD = 0x1, KRB5_PROMPT_TYPE_NEW_PASSWORD = 0x2, KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN = 0x3, - KRB5_PROMPT_TYPE_PREAUTH = 0x4 + KRB5_PROMPT_TYPE_PREAUTH = 0x4, + KRB5_PROMPT_TYPE_INFO = 0x5 } krb5_prompt_type; typedef struct _krb5_prompt { @@ -754,12 +729,23 @@ enum { KRB5_KRBHST_FLAGS_LARGE_MSG = 2 }; -typedef int (*krb5_send_and_recv_func_t)(krb5_context, - void *, - krb5_krbhst_info *, - const krb5_data *, - krb5_data *); -typedef void (*krb5_send_and_recv_close_func_t)(krb5_context, void*); +typedef krb5_error_code (*krb5_send_to_kdc_func)(krb5_context, + void *, + krb5_krbhst_info *, + const krb5_data *, + krb5_data *); + +/* flags for krb5_parse_name_flags */ +enum { + KRB5_PRINCIPAL_PARSE_NO_REALM = 1, + KRB5_PRINCIPAL_PARSE_MUST_REALM = 2 +}; + +/* flags for krb5_unparse_name_flags */ +enum { + KRB5_PRINCIPAL_UNPARSE_SHORT = 1, + KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2 +}; struct credentials; /* this is to keep the compiler happy */ struct getargs; diff --git a/source4/heimdal/lib/krb5/krb5_err.c b/source4/heimdal/lib/krb5/krb5_err.c new file mode 100644 index 0000000000..9185f729d5 --- /dev/null +++ b/source4/heimdal/lib/krb5/krb5_err.c @@ -0,0 +1,271 @@ +/* Generated from krb5_err.et */ +/* $Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $ */ + +#include <stddef.h> +#include <com_err.h> +#include "krb5_err.h" + +static const char *krb5_error_strings[] = { + /* 000 */ "No error", + /* 001 */ "Client's entry in database has expired", + /* 002 */ "Server's entry in database has expired", + /* 003 */ "Requested protocol version not supported", + /* 004 */ "Client's key is encrypted in an old master key", + /* 005 */ "Server's key is encrypted in an old master key", + /* 006 */ "Client not found in Kerberos database", + /* 007 */ "Server not found in Kerberos database", + /* 008 */ "Principal has multiple entries in Kerberos database", + /* 009 */ "Client or server has a null key", + /* 010 */ "Ticket is ineligible for postdating", + /* 011 */ "Requested effective lifetime is negative or too short", + /* 012 */ "KDC policy rejects request", + /* 013 */ "KDC can't fulfill requested option", + /* 014 */ "KDC has no support for encryption type", + /* 015 */ "KDC has no support for checksum type", + /* 016 */ "KDC has no support for padata type", + /* 017 */ "KDC has no support for transited type", + /* 018 */ "Clients credentials have been revoked", + /* 019 */ "Credentials for server have been revoked", + /* 020 */ "TGT has been revoked", + /* 021 */ "Client not yet valid - try again later", + /* 022 */ "Server not yet valid - try again later", + /* 023 */ "Password has expired", + /* 024 */ "Preauthentication failed", + /* 025 */ "Additional pre-authentication required", + /* 026 */ "Requested server and ticket don't match", + /* 027 */ "Reserved krb5 error (27)", + /* 028 */ "Reserved krb5 error (28)", + /* 029 */ "Reserved krb5 error (29)", + /* 030 */ "Reserved krb5 error (30)", + /* 031 */ "Decrypt integrity check failed", + /* 032 */ "Ticket expired", + /* 033 */ "Ticket not yet valid", + /* 034 */ "Request is a replay", + /* 035 */ "The ticket isn't for us", + /* 036 */ "Ticket/authenticator don't match", + /* 037 */ "Clock skew too great", + /* 038 */ "Incorrect net address", + /* 039 */ "Protocol version mismatch", + /* 040 */ "Invalid message type", + /* 041 */ "Message stream modified", + /* 042 */ "Message out of order", + /* 043 */ "Invalid cross-realm ticket", + /* 044 */ "Key version is not available", + /* 045 */ "Service key not available", + /* 046 */ "Mutual authentication failed", + /* 047 */ "Incorrect message direction", + /* 048 */ "Alternative authentication method required", + /* 049 */ "Incorrect sequence number in message", + /* 050 */ "Inappropriate type of checksum in message", + /* 051 */ "Policy rejects transited path", + /* 052 */ "Response too big for UDP, retry with TCP", + /* 053 */ "Reserved krb5 error (53)", + /* 054 */ "Reserved krb5 error (54)", + /* 055 */ "Reserved krb5 error (55)", + /* 056 */ "Reserved krb5 error (56)", + /* 057 */ "Reserved krb5 error (57)", + /* 058 */ "Reserved krb5 error (58)", + /* 059 */ "Reserved krb5 error (59)", + /* 060 */ "Generic error (see e-text)", + /* 061 */ "Field is too long for this implementation", + /* 062 */ "Client not trusted", + /* 063 */ "KDC not trusted", + /* 064 */ "Invalid signature", + /* 065 */ "DH parameters not accepted", + /* 066 */ "Reserved krb5 error (66)", + /* 067 */ "Reserved krb5 error (67)", + /* 068 */ "Reserved krb5 error (68)", + /* 069 */ "User to user required", + /* 070 */ "Cannot verify certificate", + /* 071 */ "Certificate invalid", + /* 072 */ "Certificate revoked", + /* 073 */ "Revocation status unknown", + /* 074 */ "Revocation status unknown", + /* 075 */ "Inconsistent key purpose", + /* 076 */ "Digest in certificate not accepted", + /* 077 */ "paChecksum must be included", + /* 078 */ "Digest in signedData not accepted", + /* 079 */ "Public key encryption not supported", + /* 080 */ "Reserved krb5 error (80)", + /* 081 */ "Reserved krb5 error (81)", + /* 082 */ "Reserved krb5 error (82)", + /* 083 */ "Reserved krb5 error (83)", + /* 084 */ "Reserved krb5 error (84)", + /* 085 */ "Reserved krb5 error (85)", + /* 086 */ "Reserved krb5 error (86)", + /* 087 */ "Reserved krb5 error (87)", + /* 088 */ "Reserved krb5 error (88)", + /* 089 */ "Reserved krb5 error (89)", + /* 090 */ "Reserved krb5 error (90)", + /* 091 */ "Reserved krb5 error (91)", + /* 092 */ "Reserved krb5 error (92)", + /* 093 */ "Reserved krb5 error (93)", + /* 094 */ "Reserved krb5 error (94)", + /* 095 */ "Reserved krb5 error (95)", + /* 096 */ "Reserved krb5 error (96)", + /* 097 */ "Reserved krb5 error (97)", + /* 098 */ "Reserved krb5 error (98)", + /* 099 */ "Reserved krb5 error (99)", + /* 100 */ "Reserved krb5 error (100)", + /* 101 */ "Reserved krb5 error (101)", + /* 102 */ "Reserved krb5 error (102)", + /* 103 */ "Reserved krb5 error (103)", + /* 104 */ "Reserved krb5 error (104)", + /* 105 */ "Reserved krb5 error (105)", + /* 106 */ "Reserved krb5 error (106)", + /* 107 */ "Reserved krb5 error (107)", + /* 108 */ "Reserved krb5 error (108)", + /* 109 */ "Reserved krb5 error (109)", + /* 110 */ "Reserved krb5 error (110)", + /* 111 */ "Reserved krb5 error (111)", + /* 112 */ "Reserved krb5 error (112)", + /* 113 */ "Reserved krb5 error (113)", + /* 114 */ "Reserved krb5 error (114)", + /* 115 */ "Reserved krb5 error (115)", + /* 116 */ "Reserved krb5 error (116)", + /* 117 */ "Reserved krb5 error (117)", + /* 118 */ "Reserved krb5 error (118)", + /* 119 */ "Reserved krb5 error (119)", + /* 120 */ "Reserved krb5 error (120)", + /* 121 */ "Reserved krb5 error (121)", + /* 122 */ "Reserved krb5 error (122)", + /* 123 */ "Reserved krb5 error (123)", + /* 124 */ "Reserved krb5 error (124)", + /* 125 */ "Reserved krb5 error (125)", + /* 126 */ "Reserved krb5 error (126)", + /* 127 */ "Reserved krb5 error (127)", + /* 128 */ "$Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $", + /* 129 */ "Invalid flag for file lock mode", + /* 130 */ "Cannot read password", + /* 131 */ "Password mismatch", + /* 132 */ "Password read interrupted", + /* 133 */ "Invalid character in component name", + /* 134 */ "Malformed representation of principal", + /* 135 */ "Can't open/find configuration file", + /* 136 */ "Improper format of configuration file", + /* 137 */ "Insufficient space to return complete information", + /* 138 */ "Invalid message type specified for encoding", + /* 139 */ "Credential cache name malformed", + /* 140 */ "Unknown credential cache type", + /* 141 */ "Matching credential not found", + /* 142 */ "End of credential cache reached", + /* 143 */ "Request did not supply a ticket", + /* 144 */ "Wrong principal in request", + /* 145 */ "Ticket has invalid flag set", + /* 146 */ "Requested principal and ticket don't match", + /* 147 */ "KDC reply did not match expectations", + /* 148 */ "Clock skew too great in KDC reply", + /* 149 */ "Client/server realm mismatch in initial ticket request", + /* 150 */ "Program lacks support for encryption type", + /* 151 */ "Program lacks support for key type", + /* 152 */ "Requested encryption type not used in message", + /* 153 */ "Program lacks support for checksum type", + /* 154 */ "Cannot find KDC for requested realm", + /* 155 */ "Kerberos service unknown", + /* 156 */ "Cannot contact any KDC for requested realm", + /* 157 */ "No local name found for principal name", + /* 158 */ "Mutual authentication failed", + /* 159 */ "Replay cache type is already registered", + /* 160 */ "No more memory to allocate (in replay cache code)", + /* 161 */ "Replay cache type is unknown", + /* 162 */ "Generic unknown RC error", + /* 163 */ "Message is a replay", + /* 164 */ "Replay I/O operation failed XXX", + /* 165 */ "Replay cache type does not support non-volatile storage", + /* 166 */ "Replay cache name parse/format error", + /* 167 */ "End-of-file on replay cache I/O", + /* 168 */ "No more memory to allocate (in replay cache I/O code)", + /* 169 */ "Permission denied in replay cache code", + /* 170 */ "I/O error in replay cache i/o code", + /* 171 */ "Generic unknown RC/IO error", + /* 172 */ "Insufficient system space to store replay information", + /* 173 */ "Can't open/find realm translation file", + /* 174 */ "Improper format of realm translation file", + /* 175 */ "Can't open/find lname translation database", + /* 176 */ "No translation available for requested principal", + /* 177 */ "Improper format of translation database entry", + /* 178 */ "Cryptosystem internal error", + /* 179 */ "Key table name malformed", + /* 180 */ "Unknown Key table type", + /* 181 */ "Key table entry not found", + /* 182 */ "End of key table reached", + /* 183 */ "Cannot write to specified key table", + /* 184 */ "Error writing to key table", + /* 185 */ "Cannot find ticket for requested realm", + /* 186 */ "DES key has bad parity", + /* 187 */ "DES key is a weak key", + /* 188 */ "Bad encryption type", + /* 189 */ "Key size is incompatible with encryption type", + /* 190 */ "Message size is incompatible with encryption type", + /* 191 */ "Credentials cache type is already registered.", + /* 192 */ "Key table type is already registered.", + /* 193 */ "Credentials cache I/O operation failed XXX", + /* 194 */ "Credentials cache file permissions incorrect", + /* 195 */ "No credentials cache file found", + /* 196 */ "Internal file credentials cache error", + /* 197 */ "Error writing to credentials cache file", + /* 198 */ "No more memory to allocate (in credentials cache code)", + /* 199 */ "Bad format in credentials cache", + /* 200 */ "No credentials found with supported encryption types", + /* 201 */ "Invalid KDC option combination (library internal error)", + /* 202 */ "Request missing second ticket", + /* 203 */ "No credentials supplied to library routine", + /* 204 */ "Bad sendauth version was sent", + /* 205 */ "Bad application version was sent (via sendauth)", + /* 206 */ "Bad response (during sendauth exchange)", + /* 207 */ "Server rejected authentication (during sendauth exchange)", + /* 208 */ "Unsupported preauthentication type", + /* 209 */ "Required preauthentication key not supplied", + /* 210 */ "Generic preauthentication failure", + /* 211 */ "Unsupported replay cache format version number", + /* 212 */ "Unsupported credentials cache format version number", + /* 213 */ "Unsupported key table format version number", + /* 214 */ "Program lacks support for address type", + /* 215 */ "Message replay detection requires rcache parameter", + /* 216 */ "Hostname cannot be canonicalized", + /* 217 */ "Cannot determine realm for host", + /* 218 */ "Conversion to service principal undefined for name type", + /* 219 */ "Initial Ticket response appears to be Version 4", + /* 220 */ "Cannot resolve KDC for requested realm", + /* 221 */ "Requesting ticket can't get forwardable tickets", + /* 222 */ "Bad principal name while trying to forward credentials", + /* 223 */ "Looping detected inside krb5_get_in_tkt", + /* 224 */ "Configuration file does not specify default realm", + /* 225 */ "Bad SAM flags in obtain_sam_padata", + /* 226 */ "Invalid encryption type in SAM challenge", + /* 227 */ "Missing checksum in SAM challenge", + /* 228 */ "Bad checksum in SAM challenge", + /* 229 */ "Reserved krb5 error (229)", + /* 230 */ "Reserved krb5 error (230)", + /* 231 */ "Reserved krb5 error (231)", + /* 232 */ "Reserved krb5 error (232)", + /* 233 */ "Reserved krb5 error (233)", + /* 234 */ "Reserved krb5 error (234)", + /* 235 */ "Reserved krb5 error (235)", + /* 236 */ "Reserved krb5 error (236)", + /* 237 */ "Reserved krb5 error (237)", + /* 238 */ "Program called an obsolete, deleted function", + /* 239 */ "Reserved krb5 error (239)", + /* 240 */ "Reserved krb5 error (240)", + /* 241 */ "Reserved krb5 error (241)", + /* 242 */ "Reserved krb5 error (242)", + /* 243 */ "Reserved krb5 error (243)", + /* 244 */ "Reserved krb5 error (244)", + /* 245 */ "Invalid key generation parameters from KDC", + /* 246 */ "Service not available", + /* 247 */ "Credential cache function not supported", + /* 248 */ "Invalid format of Kerberos lifetime or clock skew string", + NULL +}; + +#define num_errors 249 + +void initialize_krb5_error_table_r(struct et_list **list) +{ + initialize_error_table_r(list, krb5_error_strings, num_errors, ERROR_TABLE_BASE_krb5); +} + +void initialize_krb5_error_table(void) +{ + init_error_table(krb5_error_strings, ERROR_TABLE_BASE_krb5, num_errors); +} diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 4dcac40c7a..89b3c6ad40 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h,v 1.87 2006/02/09 11:36:27 lha Exp $ */ +/* $Id: krb5_locl.h,v 1.93 2006/10/20 18:13:31 lha Exp $ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -136,6 +136,8 @@ struct sockaddr_dl; #include <krb5_asn1.h> +struct send_to_kdc; + /* XXX glue for pkinit */ struct krb5_pk_identity; struct krb5_pk_cert; @@ -151,6 +153,9 @@ struct _krb5_krb_auth_data; #include <krb5.h> #include <krb5_err.h> #include <asn1_err.h> +#ifdef PKINIT +#include <hx509_err.h> +#endif #include <krb5-private.h> #include "heim_threads.h" @@ -171,10 +176,10 @@ struct _krb5_krb_auth_data; #define KRB5_BUFSIZ 1024 typedef enum { - KRB5_PA_PAC_DONT_CARE = 0, - KRB5_PA_PAC_REQ_TRUE, - KRB5_PA_PAC_REQ_FALSE -} krb5_get_init_creds_req_pac; + KRB5_INIT_CREDS_TRISTATE_UNSET = 0, + KRB5_INIT_CREDS_TRISTATE_TRUE, + KRB5_INIT_CREDS_TRISTATE_FALSE +} krb5_get_init_creds_tristate; struct _krb5_get_init_creds_opt_private { int refcount; @@ -182,12 +187,57 @@ struct _krb5_get_init_creds_opt_private { const char *password; krb5_s2k_proc key_proc; /* PA_PAC_REQUEST */ - krb5_get_init_creds_req_pac req_pac; + krb5_get_init_creds_tristate req_pac; /* PKINIT */ krb5_pk_init_ctx pk_init_ctx; int canonicalize; + KRB_ERROR *error; + krb5_get_init_creds_tristate addressless; }; +typedef struct krb5_context_data { + krb5_enctype *etypes; + krb5_enctype *etypes_des; + char **default_realms; + time_t max_skew; + time_t kdc_timeout; + unsigned max_retries; + int32_t kdc_sec_offset; + int32_t kdc_usec_offset; + krb5_config_section *cf; + struct et_list *et_list; + struct krb5_log_facility *warn_dest; + krb5_cc_ops *cc_ops; + int num_cc_ops; + const char *http_proxy; + const char *time_fmt; + krb5_boolean log_utc; + const char *default_keytab; + const char *default_keytab_modify; + krb5_boolean use_admin_kdc; + krb5_addresses *extra_addresses; + krb5_boolean scan_interfaces; /* `ifconfig -a' */ + krb5_boolean srv_lookup; /* do SRV lookups */ + krb5_boolean srv_try_txt; /* try TXT records also */ + int32_t fcache_vno; /* create cache files w/ this + version */ + int num_kt_types; /* # of registered keytab types */ + struct krb5_keytab_data *kt_types; /* registered keytab types */ + const char *date_fmt; + char *error_string; + char error_buf[256]; + krb5_addresses *ignore_addresses; + char *default_cc_name; + int pkinit_flags; + void *mutex; /* protects error_string/error_buf */ + int large_msg_size; + int dns_canonicalize_hostname; + struct send_to_kdc *send_to_kdc; + void *mem_ctx; /* Some parts of Samba4 need a valid + memory context (under the event + context) to use */ +} krb5_context_data; + /* * Configurable options */ @@ -201,7 +251,7 @@ struct _krb5_get_init_creds_opt_private { #endif #ifndef KRB5_ADDRESSLESS_DEFAULT -#define KRB5_ADDRESSLESS_DEFAULT FALSE +#define KRB5_ADDRESSLESS_DEFAULT TRUE #endif #endif /* __KRB5_LOCL_H__ */ diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index 221bd706f4..e7b2579229 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include <resolve.h> -RCSID("$Id: krbhst.c,v 1.55 2006/04/02 10:32:20 lha Exp $"); +RCSID("$Id: krbhst.c,v 1.57 2006/10/06 17:11:02 lha Exp $"); static int string_to_proto(const char *string) @@ -422,6 +422,15 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, struct addrinfo hints; char portstr[NI_MAXSERV]; + /* + * Don't try forever in case the DNS server keep returning us + * entries (like wildcard entries or the .nu TLD) + */ + if(kd->fallback_count >= 5) { + kd->flags |= KD_FALLBACK; + return 0; + } + if(kd->fallback_count == 0) asprintf(&host, "%s.%s.", serv_string, kd->realm); else @@ -659,9 +668,8 @@ common_init(krb5_context context, } /* For 'realms' without a . do not even think of going to DNS */ - if (!strchr(realm, '.')) { + if (!strchr(realm, '.')) kd->flags |= KD_CONFIG_EXISTS; - } if (flags & KRB5_KRBHST_FLAGS_LARGE_MSG) kd->flags |= KD_LARGE_MSG; diff --git a/source4/heimdal/lib/krb5/misc.c b/source4/heimdal/lib/krb5/misc.c index baf63f6d52..f04f8d9996 100644 --- a/source4/heimdal/lib/krb5/misc.c +++ b/source4/heimdal/lib/krb5/misc.c @@ -33,4 +33,53 @@ #include "krb5_locl.h" -RCSID("$Id: misc.c,v 1.5 1999/12/02 17:05:11 joda Exp $"); +RCSID("$Id: misc.c,v 1.6 2006/06/06 14:57:47 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_s4u2self_to_checksumdata(krb5_context context, + const PA_S4U2Self *self, + krb5_data *data) +{ + krb5_error_code ret; + krb5_ssize_t ssize; + krb5_storage *sp; + size_t size; + int i; + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + ret = krb5_store_int32(sp, self->name.name_type); + if (ret) + goto out; + for (i = 0; i < self->name.name_string.len; i++) { + size = strlen(self->name.name_string.val[i]); + ssize = krb5_storage_write(sp, self->name.name_string.val[i], size); + if (ssize != size) { + ret = ENOMEM; + goto out; + } + } + size = strlen(self->realm); + ssize = krb5_storage_write(sp, self->realm, size); + if (ssize != size) { + ret = ENOMEM; + goto out; + } + size = strlen(self->auth); + ssize = krb5_storage_write(sp, self->auth, size); + if (ssize != size) { + ret = ENOMEM; + goto out; + } + + ret = krb5_storage_to_data(sp, data); + krb5_storage_free(sp); + return ret; + +out: + krb5_clear_error_string(context); + return ret; +} diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c index b7f06c1582..b9075b3079 100755 --- a/source4/heimdal/lib/krb5/mit_glue.c +++ b/source4/heimdal/lib/krb5/mit_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: mit_glue.c,v 1.7 2005/05/18 04:21:44 lha Exp $"); +RCSID("$Id: mit_glue.c,v 1.8 2006/10/14 09:51:02 lha Exp $"); /* * Glue for MIT API @@ -98,7 +98,7 @@ krb5_c_get_checksum(krb5_context context, const krb5_checksum *cksum, if (*data == NULL) return ENOMEM; - ret = copy_octet_string(&cksum->checksum, *data); + ret = der_copy_octet_string(&cksum->checksum, *data); if (ret) { free(*data); *data = NULL; @@ -113,7 +113,7 @@ krb5_c_set_checksum(krb5_context context, krb5_checksum *cksum, krb5_cksumtype type, const krb5_data *data) { cksum->cksumtype = type; - return copy_octet_string(data, &cksum->checksum); + return der_copy_octet_string(data, &cksum->checksum); } void KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 00f7b4ebd9..f519b5ad08 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.99 2006/05/07 12:32:38 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.110 2006/10/14 09:52:50 lha Exp $"); struct krb5_dh_moduli { char *name; @@ -69,7 +69,7 @@ struct krb5_pk_identity { hx509_certs certs; hx509_certs anchors; hx509_certs certpool; - hx509_revoke_ctx revoke; + hx509_revoke_ctx revokectx; }; struct krb5_pk_cert { @@ -344,8 +344,8 @@ build_auth_pack(krb5_context context, ALLOC(a->clientPublicValue, 1); if (a->clientPublicValue == NULL) return ENOMEM; - ret = copy_oid(oid_id_dhpublicnumber(), - &a->clientPublicValue->algorithm.algorithm); + ret = der_copy_oid(oid_id_dhpublicnumber(), + &a->clientPublicValue->algorithm.algorithm); if (ret) return ret; @@ -392,7 +392,7 @@ build_auth_pack(krb5_context context, ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length, &dh_pub_key, &size, ret); - free_heim_integer(&dh_pub_key); + der_free_heim_integer(&dh_pub_key); if (ret) return ret; if (size != dhbuf.length) @@ -413,7 +413,7 @@ _krb5_pk_mk_ContentInfo(krb5_context context, { krb5_error_code ret; - ret = copy_oid(oid, &content_info->contentType); + ret = der_copy_oid(oid, &content_info->contentType); if (ret) return ret; ALLOC(content_info->content, 1); @@ -672,8 +672,16 @@ _krb5_pk_verify_sign(krb5_context context, contentType, content, &signer_certs); - if (ret) + if (ret) { + char *s = hx509_get_error_string(id->hx509ctx, ret); + if (s) { + krb5_set_error_string(context, + "CMS verify signed failed with %s", s); + free(s); + } else + krb5_clear_error_string(context); return ret; + } *signer = calloc(1, sizeof(**signer)); if (*signer == NULL) { @@ -833,7 +841,9 @@ pk_verify_host(krb5_context context, oid_id_pkinit_san(), &list); if (ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Failed to find the PK-INIT " + "subjectAltName in the KDC certificate"); + return ret; } @@ -845,7 +855,9 @@ pk_verify_host(krb5_context context, &r, NULL); if (ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Failed to decode the PK-INIT " + "subjectAltName in the KDC certificate"); + break; } @@ -856,7 +868,7 @@ pk_verify_host(krb5_context context, { krb5_set_error_string(context, "KDC have wrong realm name in " "the certificate"); - ret = EINVAL; + ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; } free_KRB5PrincipalName(&r); @@ -875,7 +887,8 @@ pk_verify_host(krb5_context context, hi->ai->ai_addr, hi->ai->ai_addrlen); if (ret) - krb5_set_error_string(context, "Address mismatch in the KDC certificate"); + krb5_set_error_string(context, "Address mismatch in " + "the KDC certificate"); } return ret; } @@ -901,7 +914,7 @@ pk_rd_pa_reply_enckey(krb5_context context, krb5_data content; heim_oid contentType = { 0, NULL }; - if (heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) { + if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) { krb5_set_error_string(context, "PKINIT: Invalid content type"); return EINVAL; } @@ -913,8 +926,10 @@ pk_rd_pa_reply_enckey(krb5_context context, ret = hx509_cms_unenvelope(ctx->id->hx509ctx, ctx->id->certs, + HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT, rep->content->data, rep->content->length, + NULL, &contentType, &content); if (ret) @@ -935,7 +950,7 @@ pk_rd_pa_reply_enckey(krb5_context context, goto out; } - if (heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) { + if (der_heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) { ret = EINVAL; /* XXX */ krb5_set_error_string(context, "PKINIT: Invalid content type"); goto out; @@ -964,19 +979,18 @@ pk_rd_pa_reply_enckey(krb5_context context, /* make sure that it is the kdc's certificate */ ret = pk_verify_host(context, realm, hi, ctx, host); if (ret) { - krb5_set_error_string(context, "PKINIT: failed verify host: %d", ret); goto out; } #if 0 if (type == COMPAT_WIN2K) { - if (heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) { + if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) { krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; } } else { - if (heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) { + if (der_heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) { krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; @@ -1002,7 +1016,7 @@ pk_rd_pa_reply_enckey(krb5_context context, out: if (host) _krb5_pk_cert_free(host); - free_oid(&contentType); + der_free_oid(&contentType); krb5_data_free(&content); return ret; @@ -1034,7 +1048,7 @@ pk_rd_pa_reply_dh(krb5_context context, krb5_data_zero(&content); memset(&kdc_dh_info, 0, sizeof(kdc_dh_info)); - if (heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) { + if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) { krb5_set_error_string(context, "PKINIT: Invalid content type"); return EINVAL; } @@ -1059,7 +1073,7 @@ pk_rd_pa_reply_dh(krb5_context context, if (ret) goto out; - if (heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) { + if (der_heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) { krb5_set_error_string(context, "pkinit - dh reply contains wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; @@ -1324,20 +1338,28 @@ hx_pass_prompter(void *data, const hx509_prompt *prompter) password_data.data = prompter->reply.data; password_data.length = prompter->reply.length; - prompt.prompt = "Enter your private key passphrase: "; - prompt.hidden = 1; + + prompt.prompt = prompter->prompt; + prompt.hidden = hx509_prompt_hidden(prompter->type); prompt.reply = &password_data; - if (prompter->hidden) + + switch (prompter->type) { + case HX509_PROMPT_TYPE_INFO: + prompt.type = KRB5_PROMPT_TYPE_INFO; + break; + case HX509_PROMPT_TYPE_PASSWORD: + case HX509_PROMPT_TYPE_QUESTION: + default: prompt.type = KRB5_PROMPT_TYPE_PASSWORD; - else - prompt.type = KRB5_PROMPT_TYPE_PREAUTH; /* XXX */ + break; + } ret = (*p->prompter)(p->context, p->prompter_data, NULL, NULL, 1, &prompt); if (ret) { memset (prompter->reply.data, 0, prompter->reply.length); - return 0; + return 1; } - return strlen(prompter->reply.data); + return 0; } @@ -1354,8 +1376,8 @@ _krb5_pk_load_id(krb5_context context, struct krb5_pk_identity **ret_id, const char *user_id, const char *anchor_id, - char * const *chain, - char * const *revoke, + char * const *chain_list, + char * const *revoke_list, krb5_prompter_fct prompter, void *prompter_data, char *password) @@ -1392,7 +1414,7 @@ _krb5_pk_load_id(krb5_context context, goto out; ret = hx509_lock_init(id->hx509ctx, &lock); - if (password) + if (password && password[0]) hx509_lock_add_password(lock, password); if (prompter) { @@ -1405,7 +1427,7 @@ _krb5_pk_load_id(krb5_context context, goto out; } - ret = hx509_certs_init(id->hx509ctx, user_id, 0, NULL, &id->certs); + ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs); if (ret) goto out; @@ -1418,33 +1440,36 @@ _krb5_pk_load_id(krb5_context context, if (ret) goto out; - while (chain && *chain) { - ret = hx509_certs_append(id->hx509ctx, id->certpool, NULL, *chain); + while (chain_list && *chain_list) { + ret = hx509_certs_append(id->hx509ctx, id->certpool, + NULL, *chain_list); if (ret) { krb5_set_error_string(context, "pkinit failed to load chain %s", - *chain); + *chain_list); goto out; } - chain++; + chain_list++; } - if (revoke) { - ret = hx509_revoke_init(id->hx509ctx, &id->revoke); + if (revoke_list) { + ret = hx509_revoke_init(id->hx509ctx, &id->revokectx); if (ret) { krb5_set_error_string(context, "revoke failed to init"); goto out; } - while (*revoke) { - ret = hx509_revoke_add_crl(id->hx509ctx, id->revoke, *revoke); + while (*revoke_list) { + ret = hx509_revoke_add_crl(id->hx509ctx, + id->revokectx, + *revoke_list); if (ret) { krb5_set_error_string(context, "pkinit failed to load revoke %s", - *revoke); + *revoke_list); goto out; } - revoke++; + revoke_list++; } } else hx509_context_set_missing_revoke(id->hx509ctx, 1); @@ -1454,7 +1479,7 @@ _krb5_pk_load_id(krb5_context context, goto out; hx509_verify_attach_anchors(id->verify_ctx, id->anchors); - hx509_verify_attach_revoke(id->verify_ctx, id->revoke); + hx509_verify_attach_revoke(id->verify_ctx, id->revokectx); out: if (ret) { @@ -1462,7 +1487,7 @@ out: hx509_certs_free(&id->certs); hx509_certs_free(&id->anchors); hx509_certs_free(&id->certpool); - hx509_revoke_free(&id->revoke); + hx509_revoke_free(&id->revokectx); hx509_context_free(&id->hx509ctx); free(id); } else @@ -1588,9 +1613,9 @@ _krb5_parse_moduli_line(krb5_context context, return 0; out: free(m1->name); - free_heim_integer(&m1->p); - free_heim_integer(&m1->g); - free_heim_integer(&m1->q); + der_free_heim_integer(&m1->p); + der_free_heim_integer(&m1->g); + der_free_heim_integer(&m1->q); free(m1); return ret; } @@ -1601,9 +1626,9 @@ _krb5_free_moduli(struct krb5_dh_moduli **moduli) int i; for (i = 0; moduli[i] != NULL; i++) { free(moduli[i]->name); - free_heim_integer(&moduli[i]->p); - free_heim_integer(&moduli[i]->g); - free_heim_integer(&moduli[i]->q); + der_free_heim_integer(&moduli[i]->p); + der_free_heim_integer(&moduli[i]->g); + der_free_heim_integer(&moduli[i]->q); free(moduli[i]); } free(moduli); @@ -1712,9 +1737,9 @@ _krb5_dh_group_ok(krb5_context context, unsigned long bits, *name = NULL; for (i = 0; moduli[i] != NULL; i++) { - if (heim_integer_cmp(&moduli[i]->g, g) == 0 && - heim_integer_cmp(&moduli[i]->p, p) == 0 && - (q == NULL || heim_integer_cmp(&moduli[i]->q, q) == 0)) + if (der_heim_integer_cmp(&moduli[i]->g, g) == 0 && + der_heim_integer_cmp(&moduli[i]->p, p) == 0 && + (q == NULL || der_heim_integer_cmp(&moduli[i]->q, q) == 0)) { if (bits && bits > moduli[i]->bits) { krb5_set_error_string(context, "PKINIT: DH group parameter %s " @@ -1769,8 +1794,8 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, krb5_principal principal, const char *user_id, const char *x509_anchors, - char * const * chain, - char * const * revoke, + char * const * pool, + char * const * pki_revoke, int flags, krb5_prompter_fct prompter, void *prompter_data, @@ -1778,6 +1803,7 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, { #ifdef PKINIT krb5_error_code ret; + char *anchors = NULL; if (opt->opt_private == NULL) { krb5_set_error_string(context, "PKINIT: on non extendable opt"); @@ -1797,12 +1823,33 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, opt->opt_private->pk_init_ctx->require_eku = 1; opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1; + + /* XXX implement krb5_appdefault_strings */ + if (pool == NULL) + pool = krb5_config_get_strings(context, NULL, + "appdefaults", + "pkinit-pool", + NULL); + + if (pki_revoke == NULL) + pki_revoke = krb5_config_get_strings(context, NULL, + "appdefaults", + "pkinit-revoke", + NULL); + + if (x509_anchors == NULL) { + krb5_appdefault_string(context, "kinit", + krb5_principal_get_realm(context, principal), + "pkinit-anchors", NULL, &anchors); + x509_anchors = anchors; + } + ret = _krb5_pk_load_id(context, &opt->opt_private->pk_init_ctx->id, user_id, x509_anchors, - chain, - revoke, + pool, + pki_revoke, prompter, prompter_data, password); diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index f6e3847cce..4d13e7db11 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -41,7 +41,7 @@ #include <fnmatch.h> #include "resolve.h" -RCSID("$Id: principal.c,v 1.95 2006/04/24 15:16:14 lha Exp $"); +RCSID("$Id: principal.c,v 1.99 2006/10/18 06:53:22 lha Exp $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -91,17 +91,11 @@ krb5_principal_get_comp_string(krb5_context context, return princ_ncomp(principal, component); } -enum realm_presence { - MAY, - MUSTNOT, - MUST -}; - -static krb5_error_code -parse_name(krb5_context context, - const char *name, - enum realm_presence realm_presence, - krb5_principal *principal) +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name_flags(krb5_context context, + const char *name, + int flags, + krb5_principal *principal) { krb5_error_code ret; heim_general_string *comp; @@ -117,6 +111,17 @@ parse_name(krb5_context context, char c; int got_realm = 0; + *principal = NULL; + +#define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_MUST_REALM) + + if ((flags & RFLAGS) == RFLAGS) { + krb5_set_error_string(context, "Can't require both realm and " + "no realm at the same time"); + return KRB5_ERR_NO_SERVICE; + } +#undef RFLAGS + /* count number of component */ ncomp = 1; for(p = name; *p; p++){ @@ -191,32 +196,33 @@ parse_name(krb5_context context, } *q++ = c; } - if (got_realm) { - if (realm_presence == MUSTNOT) { - krb5_set_error_string (context, "realm found in 'short' principal expected to be without one!"); + if(got_realm){ + if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { + krb5_set_error_string (context, "realm found in 'short' principal " + "expected to be without one"); ret = KRB5_PARSE_MALFORMED; goto exit; - } else { - realm = malloc(q - start + 1); - if (realm == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); - ret = ENOMEM; - goto exit; - } - memcpy(realm, start, q - start); - realm[q - start] = 0; } + realm = malloc(q - start + 1); + if (realm == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto exit; + } + memcpy(realm, start, q - start); + realm[q - start] = 0; }else{ - if (realm_presence == MAY) { - ret = krb5_get_default_realm (context, &realm); - if (ret) - goto exit; - } else if (realm_presence == MUSTNOT) { - realm = NULL; - } else if (realm_presence == MUST) { - krb5_set_error_string (context, "realm NOT found in principal expected to be with one!"); + if (flags & KRB5_PRINCIPAL_PARSE_MUST_REALM) { + krb5_set_error_string (context, "realm NOT found in principal " + "expected to be with one"); ret = KRB5_PARSE_MALFORMED; goto exit; + } else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { + realm = NULL; + } else { + ret = krb5_get_default_realm (context, &realm); + if (ret) + goto exit; } comp[n] = malloc(q - start + 1); @@ -256,24 +262,9 @@ krb5_parse_name(krb5_context context, const char *name, krb5_principal *principal) { - return parse_name(context, name, MAY, principal); + return krb5_parse_name_flags(context, name, 0, principal); } -krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_name_norealm(krb5_context context, - const char *name, - krb5_principal *principal) -{ - return parse_name(context, name, MUSTNOT, principal); -} - -krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_name_mustrealm(krb5_context context, - const char *name, - krb5_principal *principal) -{ - return parse_name(context, name, MUST, principal); -} static const char quotable_chars[] = " \n\t\b\\/@"; static const char replace_chars[] = " ntb\\/@"; @@ -301,23 +292,47 @@ unparse_name_fixed(krb5_context context, krb5_const_principal principal, char *name, size_t len, - krb5_boolean short_form) + int flags) { size_t idx = 0; int i; + int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0; + int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0; + + if (!no_realm && princ_realm(principal) == NULL) { + krb5_set_error_string(context, "Realm missing from principal, " + "can't unparse"); + return ERANGE; + } + for(i = 0; i < princ_num_comp(principal); i++){ if(i) add_char(name, idx, len, '/'); idx = quote_string(princ_ncomp(principal, i), name, idx, len); - if(idx == len) + if(idx == len) { + krb5_set_error_string(context, "Out of space printing principal"); return ERANGE; + } } /* add realm if different from default realm */ - if(!short_form) { + if(short_form && !no_realm) { + krb5_realm r; + krb5_error_code ret; + ret = krb5_get_default_realm(context, &r); + if(ret) + return ret; + if(strcmp(princ_realm(principal), r) != 0) + short_form = 0; + free(r); + } + if(!short_form && !no_realm) { add_char(name, idx, len, '@'); idx = quote_string(princ_realm(principal), name, idx, len); - if(idx == len) + if(idx == len) { + krb5_set_error_string(context, + "Out of space printing realm of principal"); return ERANGE; + } } return 0; } @@ -328,57 +343,48 @@ krb5_unparse_name_fixed(krb5_context context, char *name, size_t len) { - return unparse_name_fixed(context, principal, name, len, FALSE); + return unparse_name_fixed(context, principal, name, len, 0); } krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_norealm_fixed(krb5_context context, - krb5_const_principal principal, - char *name, - size_t len) +krb5_unparse_name_fixed_short(krb5_context context, + krb5_const_principal principal, + char *name, + size_t len) { - return unparse_name_fixed(context, principal, name, len, TRUE); + return unparse_name_fixed(context, principal, name, len, + KRB5_PRINCIPAL_UNPARSE_SHORT); } krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_fixed_short(krb5_context context, +krb5_unparse_name_fixed_flags(krb5_context context, krb5_const_principal principal, + int flags, char *name, size_t len) { - krb5_realm r; - krb5_error_code ret; - krb5_boolean short_form = TRUE; - ret = krb5_get_default_realm(context, &r); - if(ret) - return ret; - if(strcmp(princ_realm(principal), r) != 0) - short_form = 0; - free(r); - return unparse_name_fixed(context, principal, name, len, short_form); + return unparse_name_fixed(context, principal, name, len, flags); } static krb5_error_code unparse_name(krb5_context context, krb5_const_principal principal, char **name, - krb5_boolean short_flag) + int flags) { size_t len = 0, plen; int i; krb5_error_code ret; /* count length */ - if (!short_flag) { + if (princ_realm(principal)) { plen = strlen(princ_realm(principal)); + if(strcspn(princ_realm(principal), quotable_chars) == plen) len += plen; else len += 2*plen; - len++; - } else { - len = 0; + len++; /* '@' */ } - for(i = 0; i < princ_num_comp(principal); i++){ plen = strlen(princ_ncomp(principal, i)); if(strcspn(princ_ncomp(principal, i), quotable_chars) == plen) @@ -387,13 +393,13 @@ unparse_name(krb5_context context, len += 2*plen; len++; } - len++; + len++; /* '\0' */ *name = malloc(len); if(*name == NULL) { krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } - ret = unparse_name_fixed(context, principal, *name, len, short_flag); + ret = unparse_name_fixed(context, principal, *name, len, flags); if(ret) { free(*name); *name = NULL; @@ -406,32 +412,24 @@ krb5_unparse_name(krb5_context context, krb5_const_principal principal, char **name) { - return unparse_name(context, principal, name, FALSE); + return unparse_name(context, principal, name, 0); } krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_short(krb5_context context, +krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal, + int flags, char **name) { - krb5_realm r; - krb5_error_code ret; - krb5_boolean short_form = TRUE; - ret = krb5_get_default_realm(context, &r); - if(ret) - return ret; - if(strcmp(princ_realm(principal), r) != 0) - short_form = 0; - free(r); - return unparse_name(context, principal, name, short_form); + return unparse_name(context, principal, name, flags); } krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_norealm(krb5_context context, - krb5_const_principal principal, - char **name) +krb5_unparse_name_short(krb5_context context, + krb5_const_principal principal, + char **name) { - return unparse_name(context, principal, name, TRUE); + return unparse_name(context, principal, name, KRB5_PRINCIPAL_UNPARSE_SHORT); } #if 0 /* not implemented */ @@ -447,7 +445,7 @@ krb5_unparse_name_ext(krb5_context context, #endif -krb5_realm* KRB5_LIB_FUNCTION +krb5_realm * KRB5_LIB_FUNCTION krb5_princ_realm(krb5_context context, krb5_principal principal) { @@ -455,7 +453,6 @@ krb5_princ_realm(krb5_context context, } - void KRB5_LIB_FUNCTION krb5_princ_set_realm(krb5_context context, krb5_principal principal, diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index 01b5188bae..46a36c9aac 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -33,7 +33,7 @@ #include <krb5_locl.h> -RCSID("$Id: rd_cred.c,v 1.28 2006/04/02 02:27:33 lha Exp $"); +RCSID("$Id: rd_cred.c,v 1.29 2006/10/06 17:04:47 lha Exp $"); static krb5_error_code compare_addrs(krb5_context context, @@ -265,7 +265,8 @@ krb5_rd_cred(krb5_context context, krb5_abortx(context, "internal error in ASN.1 encoder"); copy_EncryptionKey (&kci->key, &creds->session); if (kci->prealm && kci->pname) - _krb5_principalname2krb5_principal (context, &creds->client, + _krb5_principalname2krb5_principal (context, + &creds->client, *kci->pname, *kci->prealm); if (kci->flags) diff --git a/source4/heimdal/lib/krb5/rd_rep.c b/source4/heimdal/lib/krb5/rd_rep.c index 53138d9f45..6b7f27c3cf 100644 --- a/source4/heimdal/lib/krb5/rd_rep.c +++ b/source4/heimdal/lib/krb5/rd_rep.c @@ -33,7 +33,7 @@ #include <krb5_locl.h> -RCSID("$Id: rd_rep.c,v 1.25 2005/06/17 07:49:33 lha Exp $"); +RCSID("$Id: rd_rep.c,v 1.26 2006/08/21 09:19:22 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_rep(krb5_context context, @@ -92,7 +92,10 @@ krb5_rd_rep(krb5_context context, if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { if ((*repl)->ctime != auth_context->authenticator->ctime || - (*repl)->cusec != auth_context->authenticator->cusec) { + (*repl)->cusec != auth_context->authenticator->cusec) + { + krb5_free_ap_rep_enc_part(context, *repl); + *repl = NULL; ret = KRB5KRB_AP_ERR_MUT_FAIL; krb5_clear_error_string (context); goto out; @@ -114,6 +117,8 @@ void KRB5_LIB_FUNCTION krb5_free_ap_rep_enc_part (krb5_context context, krb5_ap_rep_enc_part *val) { - free_EncAPRepPart (val); - free (val); + if (val) { + free_EncAPRepPart (val); + free (val); + } } diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index c0bb710a59..c424a73a34 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001, 2003 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2001, 2003 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include <krb5_locl.h> -RCSID("$Id: rd_req.c,v 1.63 2006/04/10 10:14:44 lha Exp $"); +RCSID("$Id: rd_req.c,v 1.66 2006/10/06 17:04:29 lha Exp $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -376,12 +376,14 @@ krb5_verify_ap_req2(krb5_context context, if(ret) goto out; - ret = _krb5_principalname2krb5_principal(context, - &t->server, ap_req->ticket.sname, + ret = _krb5_principalname2krb5_principal(context, + &t->server, + ap_req->ticket.sname, ap_req->ticket.realm); if (ret) goto out; - ret = _krb5_principalname2krb5_principal(context, - &t->client, t->ticket.cname, + ret = _krb5_principalname2krb5_principal(context, + &t->client, + t->ticket.cname, t->ticket.crealm); if (ret) goto out; @@ -402,10 +404,12 @@ krb5_verify_ap_req2(krb5_context context, krb5_principal p1, p2; krb5_boolean res; - _krb5_principalname2krb5_principal(context, &p1, + _krb5_principalname2krb5_principal(context, + &p1, ac->authenticator->cname, ac->authenticator->crealm); - _krb5_principalname2krb5_principal(context, &p2, + _krb5_principalname2krb5_principal(context, + &p2, t->ticket.cname, t->ticket.crealm); res = krb5_principal_compare (context, p1, p2); @@ -607,7 +611,8 @@ krb5_rd_req_return_keyblock(krb5_context context, return ret; if(server == NULL){ - _krb5_principalname2krb5_principal(context, &service, + _krb5_principalname2krb5_principal(context, + &service, ap_req.ticket.sname, ap_req.ticket.realm); server = service; diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index 0bcafa70a1..11c07c9e8f 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -33,32 +33,13 @@ #include "krb5_locl.h" -RCSID("$Id: send_to_kdc.c,v 1.58 2006/04/02 02:32:03 lha Exp $"); +RCSID("$Id: send_to_kdc.c,v 1.60 2006/10/20 18:42:01 lha Exp $"); -struct send_and_recv { - krb5_send_and_recv_func_t func; - krb5_send_and_recv_close_func_t close; - void *data; +struct send_to_kdc { + krb5_send_to_kdc_func func; + void *data; }; -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_send_recv_func(krb5_context context, - krb5_send_and_recv_func_t func, - krb5_send_and_recv_close_func_t close_fn, - void *data) -{ - free(context->send_and_recv); - context->send_and_recv = malloc(sizeof(*context->send_and_recv)); - if (!context->send_and_recv) { - return ENOMEM; - } - context->send_and_recv->func = func; - context->send_and_recv->close = close_fn; - context->send_and_recv->data = data; - return 0; -} - - /* * send the data in `req' on the socket `fd' (which is datagram iff udp) * waiting `tmout' for a reply and returning the reply in `rep'. @@ -346,7 +327,7 @@ krb5_sendto (krb5_context context, krb5_krbhst_handle handle, krb5_data *receive) { - krb5_error_code ret = 0; + krb5_error_code ret; int fd; int i; @@ -356,27 +337,22 @@ krb5_sendto (krb5_context context, while (krb5_krbhst_next(context, handle, &hi) == 0) { struct addrinfo *ai, *a; - if (context->send_and_recv) { - ret = context->send_and_recv->func(context, - context->send_and_recv->data, - hi, send_data, receive); - if (ret) { - continue; - } else if (receive->length != 0) { - return 0; - } else { - continue; - } + if (context->send_to_kdc) { + struct send_to_kdc *s = context->send_to_kdc; + + ret = (*s->func)(context, s->data, + hi, send_data, receive); + if (ret == 0 && receive->length != 0) + goto out; + continue; } if(hi->proto == KRB5_KRBHST_HTTP && context->http_proxy) { - if (send_via_proxy (context, hi, send_data, receive)) { - /* Try again, with next host */ - continue; - } else { - /* Success */ - return 0; + if (send_via_proxy (context, hi, send_data, receive) == 0) { + ret = 0; + goto out; } + continue; } ret = krb5_krbhst_get_addrinfo(context, hi, &ai); @@ -406,15 +382,16 @@ krb5_sendto (krb5_context context, break; } close (fd); - if(ret == 0 && receive->length != 0) { - return 0; - } + if(ret == 0 && receive->length != 0) + goto out; } } krb5_krbhst_reset(context, handle); } krb5_clear_error_string (context); - return KRB5_KDC_UNREACH; + ret = KRB5_KDC_UNREACH; +out: + return ret; } krb5_error_code KRB5_LIB_FUNCTION @@ -456,3 +433,27 @@ krb5_sendto_kdc_flags(krb5_context context, "unable to reach any KDC in realm %s", *realm); return ret; } + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_send_to_kdc_func(krb5_context context, + krb5_send_to_kdc_func func, + void *data) +{ + free(context->send_to_kdc); + if (func == NULL) { + context->send_to_kdc = NULL; + return 0; + } + + context->send_to_kdc = malloc(sizeof(*context->send_to_kdc)); + if (context->send_to_kdc == NULL) { + krb5_set_error_string(context, "Out of memory"); + return ENOMEM; + } + + context->send_to_kdc->func = func; + context->send_to_kdc->data = data; + return 0; +} + + diff --git a/source4/heimdal/lib/krb5/set_default_realm.c b/source4/heimdal/lib/krb5/set_default_realm.c index fd57b6fe67..965883309c 100644 --- a/source4/heimdal/lib/krb5/set_default_realm.c +++ b/source4/heimdal/lib/krb5/set_default_realm.c @@ -77,19 +77,8 @@ krb5_set_default_realm(krb5_context context, "libdefaults", "default_realm", NULL); - if (realms == NULL) { - char hostname[MAXHOSTNAMELEN]; - if (gethostname (hostname, sizeof(hostname))) { - return errno; - } - - if (strchr(hostname, '.') == NULL) { - /* There is no way we can get this mapping, as we can't do DNS */ - return KRB5_CONFIG_NODEFREALM; - } - ret = krb5_get_host_realm(context, hostname, - &realms); - } + if (realms == NULL) + ret = krb5_get_host_realm(context, NULL, &realms); } else { ret = string_to_list (context, realm, &realms); } diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index a6f4a011a1..e75f28ca5f 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store.c,v 1.58 2006/05/05 07:15:18 lha Exp $"); +RCSID("$Id: store.c,v 1.59 2006/08/18 08:39:13 lha Exp $"); #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) @@ -440,6 +440,76 @@ krb5_ret_stringz(krb5_storage *sp, return 0; } +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_stringnl(krb5_storage *sp, const char *s) +{ + size_t len = strlen(s); + ssize_t ret; + + ret = sp->store(sp, s, len); + if(ret != len) { + if(ret < 0) + return ret; + else + return sp->eof_code; + } + ret = sp->store(sp, "\n", 1); + if(ret != 1) { + if(ret < 0) + return ret; + else + return sp->eof_code; + } + + return 0; + +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_stringnl(krb5_storage *sp, + char **string) +{ + int expect_nl = 0; + char c; + char *s = NULL; + size_t len = 0; + ssize_t ret; + + while((ret = sp->fetch(sp, &c, 1)) == 1){ + char *tmp; + + if (c == '\r') { + expect_nl = 1; + continue; + } + if (expect_nl && c != '\n') { + free(s); + return KRB5_BADMSGTYPE; + } + + len++; + tmp = realloc (s, len); + if (tmp == NULL) { + free (s); + return ENOMEM; + } + s = tmp; + if(c == '\n') { + s[len - 1] = '\0'; + break; + } + s[len - 1] = c; + } + if(ret != 1){ + free(s); + if(ret == 0) + return sp->eof_code; + return ret; + } + *string = s; + return 0; +} + krb5_error_code KRB5_LIB_FUNCTION krb5_store_principal(krb5_storage *sp, diff --git a/source4/heimdal/lib/krb5/store_fd.c b/source4/heimdal/lib/krb5/store_fd.c index 46043a6761..835d3478e2 100644 --- a/source4/heimdal/lib/krb5/store_fd.c +++ b/source4/heimdal/lib/krb5/store_fd.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store_fd.c,v 1.12 2004/05/25 21:43:57 lha Exp $"); +RCSID("$Id: store_fd.c,v 1.13 2006/06/30 21:23:19 lha Exp $"); typedef struct fd_storage { int fd; @@ -74,13 +74,16 @@ krb5_storage_from_fd(int fd) fd = dup(fd); if (fd < 0) return NULL; - sp = malloc(sizeof(krb5_storage)); - if (sp == NULL) + sp = malloc(sizeof(krb5_storage)); + if (sp == NULL) { + close(fd); return NULL; + } sp->data = malloc(sizeof(fd_storage)); if (sp->data == NULL) { + close(fd); free(sp); return NULL; } diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index 99cb778722..fdc2a1b3a5 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: ticket.c,v 1.14 2005/10/27 13:21:42 lha Exp $"); +RCSID("$Id: ticket.c,v 1.15 2006/10/14 09:53:19 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_free_ticket(krb5_context context, @@ -107,12 +107,16 @@ find_type_in_ad(krb5_context context, const AuthorizationData *ad, int level) { - krb5_error_code ret = ENOENT; + /* It is not an error if nothing in here, that is reported by *found */ + /* Setting a default error causes found to be set to FALSE, on + * recursion to an second embedded authz data even if the first + * element contains the required type */ + krb5_error_code ret = 0; int i; if (level > 9) { krb5_set_error_string(context, "Authorization data nested deeper " - "than %d levels, stop searching", level); + "then %d levels, stop searching", level); ret = ENOENT; /* XXX */ goto out; } @@ -124,7 +128,7 @@ find_type_in_ad(krb5_context context, */ for (i = 0; i < ad->len; i++) { if (!*found && ad->val[i].ad_type == type) { - ret = copy_octet_string(&ad->val[i].ad_data, data); + ret = der_copy_octet_string(&ad->val[i].ad_data, data); if (ret) { krb5_set_error_string(context, "malloc - out of memory"); goto out; diff --git a/source4/heimdal/lib/roken/bswap.c b/source4/heimdal/lib/roken/bswap.c index dd7ea832af..48b587d2db 100644 --- a/source4/heimdal/lib/roken/bswap.c +++ b/source4/heimdal/lib/roken/bswap.c @@ -34,7 +34,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif -#include <roken.h> +#include "roken.h" RCSID("$Id: bswap.c,v 1.4 2005/04/12 11:28:35 lha Exp $"); diff --git a/source4/heimdal/lib/roken/copyhostent.c b/source4/heimdal/lib/roken/copyhostent.c index 7d458dc1b9..d11fa16303 100644 --- a/source4/heimdal/lib/roken/copyhostent.c +++ b/source4/heimdal/lib/roken/copyhostent.c @@ -36,7 +36,7 @@ RCSID("$Id: copyhostent.c,v 1.3 2005/04/12 11:28:36 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" /* * return a malloced copy of `h' diff --git a/source4/heimdal/lib/roken/freeaddrinfo.c b/source4/heimdal/lib/roken/freeaddrinfo.c index cd2898036b..6311aa29d8 100644 --- a/source4/heimdal/lib/roken/freeaddrinfo.c +++ b/source4/heimdal/lib/roken/freeaddrinfo.c @@ -36,7 +36,7 @@ RCSID("$Id: freeaddrinfo.c,v 1.5 2005/04/12 11:28:41 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" /* * free the list of `struct addrinfo' starting at `ai' diff --git a/source4/heimdal/lib/roken/freehostent.c b/source4/heimdal/lib/roken/freehostent.c index 1ebb01361c..d837ba2503 100644 --- a/source4/heimdal/lib/roken/freehostent.c +++ b/source4/heimdal/lib/roken/freehostent.c @@ -36,7 +36,7 @@ RCSID("$Id: freehostent.c,v 1.3 2005/04/12 11:28:41 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" /* * free a malloced hostent diff --git a/source4/heimdal/lib/roken/gai_strerror.c b/source4/heimdal/lib/roken/gai_strerror.c index 102aa75ea1..52db0f8842 100644 --- a/source4/heimdal/lib/roken/gai_strerror.c +++ b/source4/heimdal/lib/roken/gai_strerror.c @@ -36,7 +36,7 @@ RCSID("$Id: gai_strerror.c,v 1.7 2005/08/05 09:31:35 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" static struct gai_error { int code; diff --git a/source4/heimdal/lib/roken/getaddrinfo.c b/source4/heimdal/lib/roken/getaddrinfo.c index 86af8b72cc..b39131de74 100644 --- a/source4/heimdal/lib/roken/getaddrinfo.c +++ b/source4/heimdal/lib/roken/getaddrinfo.c @@ -36,7 +36,7 @@ RCSID("$Id: getaddrinfo.c,v 1.14 2005/06/16 17:49:29 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" /* * uses hints->ai_socktype and hints->ai_protocol diff --git a/source4/heimdal/lib/roken/getipnodebyaddr.c b/source4/heimdal/lib/roken/getipnodebyaddr.c index 3f447d6d06..841fc46a80 100644 --- a/source4/heimdal/lib/roken/getipnodebyaddr.c +++ b/source4/heimdal/lib/roken/getipnodebyaddr.c @@ -36,7 +36,7 @@ RCSID("$Id: getipnodebyaddr.c,v 1.3 2005/04/12 11:28:47 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" /* * lookup `src, len' (address family `af') in DNS and return a pointer diff --git a/source4/heimdal/lib/roken/getipnodebyname.c b/source4/heimdal/lib/roken/getipnodebyname.c index b928efcc53..0707e4c16c 100644 --- a/source4/heimdal/lib/roken/getipnodebyname.c +++ b/source4/heimdal/lib/roken/getipnodebyname.c @@ -36,7 +36,7 @@ RCSID("$Id: getipnodebyname.c,v 1.4 2005/04/12 11:28:47 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" #ifndef HAVE_H_ERRNO static int h_errno = NO_RECOVERY; diff --git a/source4/heimdal/lib/roken/getprogname.c b/source4/heimdal/lib/roken/getprogname.c index 7eabe40093..f8f1e9d4a2 100644 --- a/source4/heimdal/lib/roken/getprogname.c +++ b/source4/heimdal/lib/roken/getprogname.c @@ -36,7 +36,7 @@ RCSID("$Id: getprogname.c,v 1.3 2005/04/12 11:28:48 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" #ifndef HAVE___PROGNAME const char *__progname; diff --git a/source4/heimdal/lib/roken/hex.c b/source4/heimdal/lib/roken/hex.c index e41b508fcb..ba0f4a4fda 100644 --- a/source4/heimdal/lib/roken/hex.c +++ b/source4/heimdal/lib/roken/hex.c @@ -35,7 +35,7 @@ #include <config.h> RCSID("$Id: hex.c,v 1.8 2006/01/09 17:09:29 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" #include <ctype.h> #include "hex.h" diff --git a/source4/heimdal/lib/roken/hostent_find_fqdn.c b/source4/heimdal/lib/roken/hostent_find_fqdn.c index 1762b11226..24f3b843d8 100644 --- a/source4/heimdal/lib/roken/hostent_find_fqdn.c +++ b/source4/heimdal/lib/roken/hostent_find_fqdn.c @@ -36,7 +36,7 @@ RCSID("$Id: hostent_find_fqdn.c,v 1.3 2005/04/12 11:28:51 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" /* * Try to find a fqdn (with `.') in he if possible, else return h_name diff --git a/source4/heimdal/lib/roken/inet_aton.c b/source4/heimdal/lib/roken/inet_aton.c index 0483a05256..b26dcb87ff 100644 --- a/source4/heimdal/lib/roken/inet_aton.c +++ b/source4/heimdal/lib/roken/inet_aton.c @@ -36,7 +36,7 @@ RCSID("$Id: inet_aton.c,v 1.14 2005/04/12 11:28:52 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" /* Minimal implementation of inet_aton. * Cannot distinguish between failure and a local broadcast address. */ diff --git a/source4/heimdal/lib/roken/issuid.c b/source4/heimdal/lib/roken/issuid.c index e6b5248164..7ccf615451 100644 --- a/source4/heimdal/lib/roken/issuid.c +++ b/source4/heimdal/lib/roken/issuid.c @@ -36,7 +36,7 @@ RCSID("$Id: issuid.c,v 1.6 2005/05/13 07:42:03 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" int ROKEN_LIB_FUNCTION issuid(void) diff --git a/source4/heimdal/lib/roken/resolve.c b/source4/heimdal/lib/roken/resolve.c index a72fb24eab..6a14547c62 100644 --- a/source4/heimdal/lib/roken/resolve.c +++ b/source4/heimdal/lib/roken/resolve.c @@ -34,7 +34,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif -#include <roken.h> +#include "roken.h" #ifdef HAVE_ARPA_NAMESER_H #include <arpa/nameser.h> #endif diff --git a/source4/heimdal/lib/roken/roken.h b/source4/heimdal/lib/roken/roken.h index 853de9b112..9d1ead97e2 100644 --- a/source4/heimdal/lib/roken/roken.h +++ b/source4/heimdal/lib/roken/roken.h @@ -1,6 +1,12 @@ +/* This is an OS dependent, generated file */ + + +#ifndef __ROKEN_H__ +#define __ROKEN_H__ + /* -*- C -*- */ /* - * Copyright (c) 1995-2005 Kungliga Tekniska Högskolan + * Copyright (c) 1995-2005 Kungliga Tekniska H * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -32,375 +38,122 @@ * SUCH DAMAGE. */ -/* $Id: roken.h.in,v 1.178 2005/09/28 03:04:54 lha Exp $ */ +/* $Id: roken.h.in,v 1.182 2006/10/19 16:35:16 lha Exp $ */ #include <stdio.h> #include <stdlib.h> #include <stdarg.h> -#ifdef HAVE_STDINT_H #include <stdint.h> -#endif #include <string.h> #include <signal.h> -#ifdef _AIX -struct ether_addr; -struct sockaddr_dl; -#endif -#ifdef HAVE_SYS_PARAM_H #include <sys/param.h> -#endif -#ifdef HAVE_INTTYPES_H #include <inttypes.h> -#endif -#ifdef HAVE_SYS_TYPES_H #include <sys/types.h> -#endif -#ifdef HAVE_SYS_BITYPES_H #include <sys/bitypes.h> -#endif -#ifdef HAVE_BIND_BITYPES_H -#include <bind/bitypes.h> -#endif -#ifdef HAVE_NETINET_IN6_MACHTYPES_H -#include <netinet/in6_machtypes.h> -#endif -#ifdef HAVE_UNISTD_H #include <unistd.h> -#endif -#ifdef HAVE_SYS_SOCKET_H #include <sys/socket.h> -#endif -#ifdef HAVE_SYS_UIO_H #include <sys/uio.h> -#endif -#ifdef HAVE_GRP_H #include <grp.h> -#endif -#ifdef HAVE_SYS_STAT_H #include <sys/stat.h> -#endif -#ifdef HAVE_NETINET_IN_H #include <netinet/in.h> -#endif -#ifdef HAVE_NETINET_IN6_H -#include <netinet/in6.h> -#endif -#ifdef HAVE_NETINET6_IN6_H -#include <netinet6/in6.h> -#endif -#ifdef HAVE_ARPA_INET_H #include <arpa/inet.h> -#endif -#ifdef HAVE_NETDB_H #include <netdb.h> -#endif -#ifdef HAVE_ARPA_NAMESER_H #include <arpa/nameser.h> -#endif -#ifdef HAVE_RESOLV_H #include <resolv.h> -#endif -#ifdef HAVE_SYSLOG_H #include <syslog.h> -#endif -#ifdef HAVE_FCNTL_H #include <fcntl.h> -#endif -#ifdef HAVE_ERRNO_H #include <errno.h> -#endif #include <err.h> -#ifdef HAVE_TERMIOS_H #include <termios.h> -#endif -#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40 #include <sys/ioctl.h> -#endif -#ifdef TIME_WITH_SYS_TIME #include <sys/time.h> #include <time.h> -#elif defined(HAVE_SYS_TIME_H) -#include <sys/time.h> -#else -#include <time.h> -#endif -#ifdef HAVE_STRINGS_H #include <strings.h> -#endif -#ifdef HAVE_PATHS_H #include <paths.h> -#endif -#ifndef HAVE_SSIZE_T -typedef int ssize_t; -#endif #include <roken-common.h> ROKEN_CPP_START -#ifdef HAVE_UINTPTR_T #define rk_UNCONST(x) ((void *)(uintptr_t)(const void *)(x)) -#else -#define rk_UNCONST(x) ((void *)(unsigned long)(const void *)(x)) -#endif -#if !defined(HAVE_SETSID) && defined(HAVE__SETSID) -#define setsid _setsid -#endif -#ifndef HAVE_PUTENV -int ROKEN_LIB_FUNCTION putenv(const char *); -#endif -#if !defined(HAVE_SETENV) || defined(NEED_SETENV_PROTO) -int ROKEN_LIB_FUNCTION setenv(const char *, const char *, int); -#endif -#if !defined(HAVE_UNSETENV) || defined(NEED_UNSETENV_PROTO) -void ROKEN_LIB_FUNCTION unsetenv(const char *); -#endif -#if !defined(HAVE_GETUSERSHELL) || defined(NEED_GETUSERSHELL_PROTO) -char * ROKEN_LIB_FUNCTION getusershell(void); -void ROKEN_LIB_FUNCTION endusershell(void); -#endif -#if !defined(HAVE_SNPRINTF) || defined(NEED_SNPRINTF_PROTO) -int ROKEN_LIB_FUNCTION snprintf (char *, size_t, const char *, ...) - __attribute__ ((format (printf, 3, 4))); -#endif -#if !defined(HAVE_VSNPRINTF) || defined(NEED_VSNPRINTF_PROTO) -int ROKEN_LIB_FUNCTION - vsnprintf (char *, size_t, const char *, va_list) - __attribute__((format (printf, 3, 0))); -#endif -#if !defined(HAVE_ASPRINTF) || defined(NEED_ASPRINTF_PROTO) -int ROKEN_LIB_FUNCTION - asprintf (char **, const char *, ...) - __attribute__ ((format (printf, 2, 3))); -#endif -#if !defined(HAVE_VASPRINTF) || defined(NEED_VASPRINTF_PROTO) -int ROKEN_LIB_FUNCTION - vasprintf (char **, const char *, va_list) - __attribute__((format (printf, 2, 0))); -#endif -#if !defined(HAVE_ASNPRINTF) || defined(NEED_ASNPRINTF_PROTO) int ROKEN_LIB_FUNCTION asnprintf (char **, size_t, const char *, ...) __attribute__ ((format (printf, 3, 4))); -#endif -#if !defined(HAVE_VASNPRINTF) || defined(NEED_VASNPRINTF_PROTO) int ROKEN_LIB_FUNCTION vasnprintf (char **, size_t, const char *, va_list) __attribute__((format (printf, 3, 0))); -#endif -#ifndef HAVE_STRDUP -char * ROKEN_LIB_FUNCTION strdup(const char *); -#endif -#if !defined(HAVE_STRNDUP) || defined(NEED_STRNDUP_PROTO) -char * ROKEN_LIB_FUNCTION strndup(const char *, size_t); -#endif -#ifndef HAVE_STRLWR char * ROKEN_LIB_FUNCTION strlwr(char *); -#endif -#ifndef HAVE_STRNLEN -size_t ROKEN_LIB_FUNCTION strnlen(const char*, size_t); -#endif -#if !defined(HAVE_STRSEP) || defined(NEED_STRSEP_PROTO) -char * ROKEN_LIB_FUNCTION strsep(char**, const char*); -#endif -#if !defined(HAVE_STRSEP_COPY) || defined(NEED_STRSEP_COPY_PROTO) ssize_t ROKEN_LIB_FUNCTION strsep_copy(const char**, const char*, char*, size_t); -#endif -#ifndef HAVE_STRCASECMP -int ROKEN_LIB_FUNCTION strcasecmp(const char *, const char *); -#endif -#ifdef NEED_FCLOSE_PROTO -int ROKEN_LIB_FUNCTION fclose(FILE *); -#endif -#ifdef NEED_STRTOK_R_PROTO -char * ROKEN_LIB_FUNCTION strtok_r(char *, const char *, char **); -#endif -#ifndef HAVE_STRUPR char * ROKEN_LIB_FUNCTION strupr(char *); -#endif -#ifndef HAVE_STRLCPY size_t ROKEN_LIB_FUNCTION strlcpy (char *, const char *, size_t); -#endif -#ifndef HAVE_STRLCAT size_t ROKEN_LIB_FUNCTION strlcat (char *, const char *, size_t); -#endif -#ifndef HAVE_GETDTABLESIZE -int ROKEN_LIB_FUNCTION getdtablesize(void); -#endif -#if !defined(HAVE_STRERROR) && !defined(strerror) -char * ROKEN_LIB_FUNCTION strerror(int); -#endif -#if !defined(HAVE_HSTRERROR) || defined(NEED_HSTRERROR_PROTO) -/* This causes a fatal error under Psoriasis */ -#if !(defined(SunOS) && (SunOS >= 50)) -const char * ROKEN_LIB_FUNCTION hstrerror(int); -#endif -#endif -#if !HAVE_DECL_H_ERRNO -extern int h_errno; -#endif -#if !defined(HAVE_INET_ATON) || defined(NEED_INET_ATON_PROTO) -int ROKEN_LIB_FUNCTION inet_aton(const char *, struct in_addr *); -#endif -#ifndef HAVE_INET_NTOP -const char * ROKEN_LIB_FUNCTION -inet_ntop(int af, const void *src, char *dst, size_t size); -#endif -#ifndef HAVE_INET_PTON -int ROKEN_LIB_FUNCTION -inet_pton(int, const char *, void *); -#endif -#if !defined(HAVE_GETCWD) -char* ROKEN_LIB_FUNCTION getcwd(char *, size_t); -#endif -#ifdef HAVE_PWD_H #include <pwd.h> struct passwd * ROKEN_LIB_FUNCTION k_getpwnam (const char *); struct passwd * ROKEN_LIB_FUNCTION k_getpwuid (uid_t); -#endif const char * ROKEN_LIB_FUNCTION get_default_username (void); -#ifndef HAVE_SETEUID -int ROKEN_LIB_FUNCTION seteuid(uid_t); -#endif -#ifndef HAVE_SETEGID -int ROKEN_LIB_FUNCTION setegid(gid_t); -#endif -#ifndef HAVE_LSTAT -int ROKEN_LIB_FUNCTION lstat(const char *, struct stat *); -#endif -#if !defined(HAVE_MKSTEMP) || defined(NEED_MKSTEMP_PROTO) int ROKEN_LIB_FUNCTION mkstemp(char *); -#endif -#ifndef HAVE_CGETENT int ROKEN_LIB_FUNCTION cgetent(char **, char **, const char *); int ROKEN_LIB_FUNCTION cgetstr(char *, const char *, char **); -#endif -#ifndef HAVE_INITGROUPS -int ROKEN_LIB_FUNCTION initgroups(const char *, gid_t); -#endif -#ifndef HAVE_FCHOWN -int ROKEN_LIB_FUNCTION fchown(int, uid_t, gid_t); -#endif -#if !defined(HAVE_DAEMON) || defined(NEED_DAEMON_PROTO) -int ROKEN_LIB_FUNCTION daemon(int, int); -#endif -#ifndef HAVE_INNETGR -int ROKEN_LIB_FUNCTION innetgr(const char *, const char *, - const char *, const char *); -#endif -#ifndef HAVE_CHOWN -int ROKEN_LIB_FUNCTION chown(const char *, uid_t, gid_t); -#endif -#ifndef HAVE_RCMD -int ROKEN_LIB_FUNCTION - rcmd(char **, unsigned short, const char *, - const char *, const char *, int *); -#endif - -#if !defined(HAVE_INNETGR) || defined(NEED_INNETGR_PROTO) -int ROKEN_LIB_FUNCTION innetgr(const char*, const char*, - const char*, const char*); -#endif - -#ifndef HAVE_IRUSEROK -int ROKEN_LIB_FUNCTION iruserok(unsigned, int, - const char *, const char *); -#endif - -#if !defined(HAVE_GETHOSTNAME) || defined(NEED_GETHOSTNAME_PROTO) -int ROKEN_LIB_FUNCTION gethostname(char *, int); -#endif - -#ifndef HAVE_WRITEV -ssize_t ROKEN_LIB_FUNCTION -writev(int, const struct iovec *, int); -#endif - -#ifndef HAVE_READV -ssize_t ROKEN_LIB_FUNCTION -readv(int, const struct iovec *, int); -#endif - -#ifndef HAVE_MKSTEMP -int ROKEN_LIB_FUNCTION -mkstemp(char *); -#endif -#ifndef HAVE_PIDFILE + + + + + + void ROKEN_LIB_FUNCTION pidfile (const char*); -#endif -#ifndef HAVE_BSWAP32 unsigned int ROKEN_LIB_FUNCTION bswap32(unsigned int); -#endif -#ifndef HAVE_BSWAP16 unsigned short ROKEN_LIB_FUNCTION bswap16(unsigned short); -#endif - -#ifndef HAVE_FLOCK -#ifndef LOCK_SH -#define LOCK_SH 1 /* Shared lock */ -#endif -#ifndef LOCK_EX -#define LOCK_EX 2 /* Exclusive lock */ -#endif -#ifndef LOCK_NB -#define LOCK_NB 4 /* Don't block when locking */ -#endif -#ifndef LOCK_UN -#define LOCK_UN 8 /* Unlock */ -#endif - -int flock(int fd, int operation); -#endif /* HAVE_FLOCK */ + time_t ROKEN_LIB_FUNCTION tm2time (struct tm, int); @@ -421,140 +174,30 @@ ssize_t ROKEN_LIB_FUNCTION net_read (int, void *, size_t); int ROKEN_LIB_FUNCTION issuid(void); -#ifndef HAVE_STRUCT_WINSIZE -struct winsize { - unsigned short ws_row, ws_col; - unsigned short ws_xpixel, ws_ypixel; -}; -#endif int ROKEN_LIB_FUNCTION get_window_size(int fd, struct winsize *); -#ifndef HAVE_VSYSLOG -void ROKEN_LIB_FUNCTION vsyslog(int, const char *, va_list); -#endif - -#if !HAVE_DECL_OPTARG -extern char *optarg; -#endif -#if !HAVE_DECL_OPTIND -extern int optind; -#endif -#if !HAVE_DECL_OPTERR -extern int opterr; -#endif - -#if !HAVE_DECL_ENVIRON -extern char **environ; -#endif - -#ifndef HAVE_GETIPNODEBYNAME + + + struct hostent * ROKEN_LIB_FUNCTION getipnodebyname (const char *, int, int, int *); -#endif -#ifndef HAVE_GETIPNODEBYADDR struct hostent * ROKEN_LIB_FUNCTION getipnodebyaddr (const void *, size_t, int, int *); -#endif -#ifndef HAVE_FREEHOSTENT void ROKEN_LIB_FUNCTION freehostent (struct hostent *); -#endif -#ifndef HAVE_COPYHOSTENT struct hostent * ROKEN_LIB_FUNCTION copyhostent (const struct hostent *); -#endif -#ifndef HAVE_SOCKLEN_T -typedef int socklen_t; -#endif -#ifndef HAVE_STRUCT_SOCKADDR_STORAGE -#ifndef HAVE_SA_FAMILY_T -typedef unsigned short sa_family_t; -#endif -#ifdef HAVE_IPV6 -#define _SS_MAXSIZE sizeof(struct sockaddr_in6) -#else -#define _SS_MAXSIZE sizeof(struct sockaddr_in) -#endif -#define _SS_ALIGNSIZE sizeof(unsigned long) -#if HAVE_STRUCT_SOCKADDR_SA_LEN -typedef unsigned char roken_sa_family_t; - -#define _SS_PAD1SIZE ((2 * _SS_ALIGNSIZE - sizeof (roken_sa_family_t) - sizeof(unsigned char)) % _SS_ALIGNSIZE) -#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (roken_sa_family_t) + sizeof(unsigned char) + _SS_PAD1SIZE + _SS_ALIGNSIZE)) - -struct sockaddr_storage { - unsigned char ss_len; - roken_sa_family_t ss_family; - char __ss_pad1[_SS_PAD1SIZE]; - unsigned long __ss_align[_SS_PAD2SIZE / sizeof(unsigned long) + 1]; -}; - -#else /* !HAVE_STRUCT_SOCKADDR_SA_LEN */ - -typedef unsigned short roken_sa_family_t; - -#define _SS_PAD1SIZE ((2 * _SS_ALIGNSIZE - sizeof (roken_sa_family_t)) % _SS_ALIGNSIZE) -#define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (roken_sa_family_t) + _SS_PAD1SIZE + _SS_ALIGNSIZE)) - -struct sockaddr_storage { - roken_sa_family_t ss_family; - char __ss_pad1[_SS_PAD1SIZE]; - unsigned long __ss_align[_SS_PAD2SIZE / sizeof(unsigned long) + 1]; -}; - -#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */ - -#endif /* HAVE_STRUCT_SOCKADDR_STORAGE */ - -#ifndef HAVE_STRUCT_ADDRINFO -struct addrinfo { - int ai_flags; - int ai_family; - int ai_socktype; - int ai_protocol; - size_t ai_addrlen; - char *ai_canonname; - struct sockaddr *ai_addr; - struct addrinfo *ai_next; -}; -#endif - -#ifndef HAVE_GETADDRINFO -int ROKEN_LIB_FUNCTION -getaddrinfo(const char *, - const char *, - const struct addrinfo *, - struct addrinfo **); -#endif - -#ifndef HAVE_GETNAMEINFO -int ROKEN_LIB_FUNCTION -getnameinfo(const struct sockaddr *, socklen_t, - char *, size_t, - char *, size_t, - int); -#endif - -#ifndef HAVE_FREEADDRINFO -void ROKEN_LIB_FUNCTION -freeaddrinfo(struct addrinfo *); -#endif - -#ifndef HAVE_GAI_STRERROR -const char * ROKEN_LIB_FUNCTION -gai_strerror(int); -#endif int ROKEN_LIB_FUNCTION getnameinfo_verified(const struct sockaddr *, socklen_t, @@ -567,130 +210,68 @@ roken_getaddrinfo_hostspec(const char *, int, struct addrinfo **); int ROKEN_LIB_FUNCTION roken_getaddrinfo_hostspec2(const char *, int, int, struct addrinfo **); -#ifndef HAVE_STRFTIME -size_t ROKEN_LIB_FUNCTION -strftime (char *, size_t, const char *, const struct tm *); -#endif -#ifndef HAVE_STRPTIME -char * ROKEN_LIB_FUNCTION -strptime (const char *, const char *, struct tm *); -#endif -#ifndef HAVE_EMALLOC void * ROKEN_LIB_FUNCTION emalloc (size_t); -#endif -#ifndef HAVE_ECALLOC void * ROKEN_LIB_FUNCTION ecalloc(size_t, size_t); -#endif -#ifndef HAVE_EREALLOC void * ROKEN_LIB_FUNCTION erealloc (void *, size_t); -#endif -#ifndef HAVE_ESTRDUP char * ROKEN_LIB_FUNCTION estrdup (const char *); -#endif /* * kludges and such */ -#if 1 int ROKEN_LIB_FUNCTION roken_gethostby_setup(const char*, const char*); struct hostent* ROKEN_LIB_FUNCTION roken_gethostbyname(const char*); struct hostent* ROKEN_LIB_FUNCTION roken_gethostbyaddr(const void*, size_t, int); -#else -#ifdef GETHOSTBYNAME_PROTO_COMPATIBLE -#define roken_gethostbyname(x) gethostbyname(x) -#else -#define roken_gethostbyname(x) gethostbyname((char *)x) -#endif - -#ifdef GETHOSTBYADDR_PROTO_COMPATIBLE -#define roken_gethostbyaddr(a, l, t) gethostbyaddr(a, l, t) -#else -#define roken_gethostbyaddr(a, l, t) gethostbyaddr((char *)a, l, t) -#endif -#endif - -#ifdef GETSERVBYNAME_PROTO_COMPATIBLE + #define roken_getservbyname(x,y) getservbyname(x,y) -#else -#define roken_getservbyname(x,y) getservbyname((char *)x, (char *)y) -#endif -#ifdef OPENLOG_PROTO_COMPATIBLE #define roken_openlog(a,b,c) openlog(a,b,c) -#else -#define roken_openlog(a,b,c) openlog((char *)a,b,c) -#endif -#ifdef GETSOCKNAME_PROTO_COMPATIBLE #define roken_getsockname(a,b,c) getsockname(a,b,c) -#else -#define roken_getsockname(a,b,c) getsockname(a, b, (void*)c) -#endif -#ifndef HAVE_SETPROGNAME void ROKEN_LIB_FUNCTION setprogname(const char *); -#endif -#ifndef HAVE_GETPROGNAME const char * ROKEN_LIB_FUNCTION getprogname(void); -#endif -#if !defined(HAVE_SETPROGNAME) && !defined(HAVE_GETPROGNAME) && !HAVE_DECL___PROGNAME extern const char *__progname; -#endif void ROKEN_LIB_FUNCTION mini_inetd_addrinfo (struct addrinfo*); void ROKEN_LIB_FUNCTION mini_inetd (int); -#ifndef HAVE_LOCALTIME_R -struct tm * ROKEN_LIB_FUNCTION -localtime_r(const time_t *, struct tm *); -#endif -#if !defined(HAVE_STRSVIS) || defined(NEED_STRSVIS_PROTO) int ROKEN_LIB_FUNCTION strsvis(char *, const char *, int, const char *); -#endif -#if !defined(HAVE_STRUNVIS) || defined(NEED_STRUNVIS_PROTO) int ROKEN_LIB_FUNCTION strunvis(char *, const char *); -#endif -#if !defined(HAVE_STRVIS) || defined(NEED_STRVIS_PROTO) int ROKEN_LIB_FUNCTION strvis(char *, const char *, int); -#endif -#if !defined(HAVE_STRVISX) || defined(NEED_STRVISX_PROTO) int ROKEN_LIB_FUNCTION strvisx(char *, const char *, size_t, int); -#endif -#if !defined(HAVE_SVIS) || defined(NEED_SVIS_PROTO) char * ROKEN_LIB_FUNCTION svis(char *, int, int, int, const char *); -#endif -#if !defined(HAVE_UNVIS) || defined(NEED_UNVIS_PROTO) int ROKEN_LIB_FUNCTION unvis(char *, int, int *, int); -#endif -#if !defined(HAVE_VIS) || defined(NEED_VIS_PROTO) char * ROKEN_LIB_FUNCTION vis(char *, int, int, int); -#endif -#if !defined(HAVE_CLOSEFROM) int ROKEN_LIB_FUNCTION closefrom(int); -#endif + + +#include <socket_wrapper.h> ROKEN_CPP_END +#define ROKEN_VERSION 0.8pre-samba + +#endif /* __ROKEN_H__ */ diff --git a/source4/heimdal/lib/roken/setprogname.c b/source4/heimdal/lib/roken/setprogname.c index c13e8d4ee1..315fa52e50 100644 --- a/source4/heimdal/lib/roken/setprogname.c +++ b/source4/heimdal/lib/roken/setprogname.c @@ -36,7 +36,7 @@ RCSID("$Id: setprogname.c,v 1.4 2005/08/23 10:19:20 lha Exp $"); #endif -#include <roken.h> +#include "roken.h" #ifndef HAVE___PROGNAME extern const char *__progname; diff --git a/source4/heimdal/lib/roken/signal.c b/source4/heimdal/lib/roken/signal.c index 7076847fb3..d92742d9fb 100644 --- a/source4/heimdal/lib/roken/signal.c +++ b/source4/heimdal/lib/roken/signal.c @@ -37,7 +37,7 @@ RCSID("$Id: signal.c,v 1.13 2005/04/12 11:29:05 lha Exp $"); #endif #include <signal.h> -#include <roken.h> +#include "roken.h" /* * We would like to always use this signal but there is a link error diff --git a/source4/heimdal/lib/roken/strsep.c b/source4/heimdal/lib/roken/strsep.c index f08c33b7a5..e34c10fe26 100644 --- a/source4/heimdal/lib/roken/strsep.c +++ b/source4/heimdal/lib/roken/strsep.c @@ -38,7 +38,7 @@ RCSID("$Id: strsep.c,v 1.4 2005/04/12 11:29:10 lha Exp $"); #include <string.h> -#include <roken.h> +#include "roken.h" #ifndef HAVE_STRSEP diff --git a/source4/heimdal/lib/roken/strsep_copy.c b/source4/heimdal/lib/roken/strsep_copy.c index 34759fe15c..5149838547 100644 --- a/source4/heimdal/lib/roken/strsep_copy.c +++ b/source4/heimdal/lib/roken/strsep_copy.c @@ -38,7 +38,7 @@ RCSID("$Id: strsep_copy.c,v 1.5 2005/04/12 11:29:11 lha Exp $"); #include <string.h> -#include <roken.h> +#include "roken.h" #ifndef HAVE_STRSEP_COPY diff --git a/source4/heimdal_build/asn1_deps.pl b/source4/heimdal_build/asn1_deps.pl index 9c4a65976b..74a77d041b 100755 --- a/source4/heimdal_build/asn1_deps.pl +++ b/source4/heimdal_build/asn1_deps.pl @@ -7,7 +7,7 @@ use File::Basename; my $file = shift; my $prefix = shift; -my $options = shift; +my $options = join(' ', @ARGV); my $x_file; my @x_files = (); my $c_file; @@ -24,7 +24,7 @@ my $header = "$dirname/$prefix.h"; print "$header: $file bin/asn1_compile\n"; print "\t\@echo \"Compiling ASN1 file $file\"\n"; -print "\t\@cd $dirname && ../../../bin/asn1_compile $options $basename $prefix\n\n"; +print "\t\@startdir=`pwd` && cd $dirname && " . ' $$startdir/bin/asn1_compile ' . "$options $basename $prefix\n\n"; open(IN,$file) or die("Can't open $file: $!"); foreach(<IN>) { diff --git a/source4/heimdal_build/config.mk b/source4/heimdal_build/config.mk index e955c28fa6..cd476765b3 100644 --- a/source4/heimdal_build/config.mk +++ b/source4/heimdal_build/config.mk @@ -5,14 +5,26 @@ CFLAGS = -Iheimdal_build -Iheimdal/kdc OBJ_FILES = \ ../heimdal/kdc/default_config.o \ ../heimdal/kdc/kerberos5.o \ + ../heimdal/kdc/krb5tgs.o \ ../heimdal/kdc/pkinit.o \ ../heimdal/kdc/log.o \ ../heimdal/kdc/misc.o \ ../heimdal/kdc/524.o \ ../heimdal/kdc/kerberos4.o \ ../heimdal/kdc/kaserver.o \ - ../heimdal/kdc/process.o -PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN HEIMDAL_KRB5 HEIMDAL_HDB + ../heimdal/kdc/digest.o \ + ../heimdal/kdc/process.o \ + ../heimdal/lib/asn1/asn1_DigestREQ.o \ + ../heimdal/lib/asn1/asn1_DigestRequest.o \ + ../heimdal/lib/asn1/asn1_DigestInit.o \ + ../heimdal/lib/asn1/asn1_DigestReqInner.o \ + ../heimdal/lib/asn1/asn1_DigestREP.o \ + ../heimdal/lib/asn1/asn1_DigestRepInner.o \ + ../heimdal/lib/asn1/asn1_DigestResponse.o \ + ../heimdal/lib/asn1/asn1_DigestInitReply.o \ + ../heimdal/lib/asn1/asn1_DigestError.o \ + ../heimdal/lib/asn1/asn1_KRB5SignedPath.o +PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN HEIMDAL_KRB5 HEIMDAL_HDB HEIMDAL_ASN1 HEIMDAL_DES # End SUBSYSTEM HEIMDAL_KDC ####################### @@ -42,61 +54,136 @@ OBJ_FILES = \ ../heimdal/lib/hdb/asn1_HDB_Ext_Constrained_delegation_acl.o \ ../heimdal/lib/hdb/asn1_HDB_Ext_Lan_Manager_OWF.o \ ../heimdal/lib/hdb/asn1_HDB_Ext_PKINIT_acl.o \ - ../heimdal/lib/hdb/asn1_HDB_Ext_PKINIT_certificate.o \ + ../heimdal/lib/hdb/asn1_HDB_Ext_PKINIT_hash.o \ ../heimdal/lib/hdb/asn1_HDB_Ext_Password.o \ ../heimdal/lib/hdb/asn1_HDB_extension.o \ ../heimdal/lib/hdb/asn1_HDB_extensions.o \ ../heimdal/lib/hdb/asn1_hdb_entry.o \ ../heimdal/lib/hdb/hdb_err.o -PUBLIC_DEPENDENCIES = HDB_LDB HEIMDAL_HDB_KEYS HEIMDAL_ROKEN +PRIVATE_DEPENDENCIES = HDB_LDB HEIMDAL_HDB_KEYS HEIMDAL_ROKEN # End SUBSYSTEM HEIMDAL_HDB ####################### ####################### # Start SUBSYSTEM HEIMDAL_GSSAPI [SUBSYSTEM::HEIMDAL_GSSAPI] -CFLAGS = -Iheimdal_build -Iheimdal/lib/gssapi +CFLAGS = -Iheimdal_build -Iheimdal/lib/gssapi/spnego -Iheimdal/lib/gssapi -Iheimdal/lib/gssapi/krb5 -I heimdal/lib/gssapi/mech OBJ_FILES = \ - ../heimdal/lib/gssapi/init_sec_context.o \ - ../heimdal/lib/gssapi/inquire_cred.o \ - ../heimdal/lib/gssapi/release_buffer.o \ - ../heimdal/lib/gssapi/release_cred.o \ - ../heimdal/lib/gssapi/release_name.o \ - ../heimdal/lib/gssapi/release_oid_set.o \ - ../heimdal/lib/gssapi/sequence.o \ - ../heimdal/lib/gssapi/test_oid_set_member.o \ - ../heimdal/lib/gssapi/unwrap.o \ - ../heimdal/lib/gssapi/verify_mic.o \ - ../heimdal/lib/gssapi/wrap.o \ - ../heimdal/lib/gssapi/address_to_krb5addr.o \ - ../heimdal/lib/gssapi/asn1_ContextFlags.o \ - ../heimdal/lib/gssapi/asn1_MechType.o \ - ../heimdal/lib/gssapi/asn1_MechTypeList.o \ - ../heimdal/lib/gssapi/asn1_NegotiationToken.o \ - ../heimdal/lib/gssapi/asn1_NegTokenInit.o \ - ../heimdal/lib/gssapi/asn1_NegTokenTarg.o \ - ../heimdal/lib/gssapi/8003.o \ - ../heimdal/lib/gssapi/accept_sec_context.o \ - ../heimdal/lib/gssapi/acquire_cred.o \ - ../heimdal/lib/gssapi/add_oid_set_member.o \ - ../heimdal/lib/gssapi/arcfour.o \ - ../heimdal/lib/gssapi/ccache_name.o \ - ../heimdal/lib/gssapi/copy_ccache.o \ - ../heimdal/lib/gssapi/cfx.o \ - ../heimdal/lib/gssapi/compat.o \ - ../heimdal/lib/gssapi/context_time.o \ - ../heimdal/lib/gssapi/create_emtpy_oid_set.o \ - ../heimdal/lib/gssapi/decapsulate.o \ - ../heimdal/lib/gssapi/delete_sec_context.o \ - ../heimdal/lib/gssapi/display_name.o \ - ../heimdal/lib/gssapi/display_status.o \ - ../heimdal/lib/gssapi/duplicate_name.o \ - ../heimdal/lib/gssapi/encapsulate.o \ - ../heimdal/lib/gssapi/external.o \ - ../heimdal/lib/gssapi/get_mic.o \ - ../heimdal/lib/gssapi/import_name.o \ - ../heimdal/lib/gssapi/init.o -PUBLIC_DEPENDENCIES = HEIMDAL_KRB5 + ../heimdal/lib/gssapi/mech/gss_krb5.o \ + ../heimdal/lib/gssapi/mech/gss_mech_switch.o \ + ../heimdal/lib/gssapi/mech/gss_process_context_token.o \ + ../heimdal/lib/gssapi/mech/gss_buffer_set.o \ + ../heimdal/lib/gssapi/mech/gss_add_cred.o \ + ../heimdal/lib/gssapi/mech/gss_add_oid_set_member.o \ + ../heimdal/lib/gssapi/mech/gss_compare_name.o \ + ../heimdal/lib/gssapi/mech/gss_release_oid_set.o \ + ../heimdal/lib/gssapi/mech/gss_create_empty_oid_set.o \ + ../heimdal/lib/gssapi/mech/gss_decapsulate_token.o \ + ../heimdal/lib/gssapi/mech/gss_inquire_cred_by_oid.o \ + ../heimdal/lib/gssapi/mech/gss_canonicalize_name.o \ + ../heimdal/lib/gssapi/mech/gss_inquire_sec_context_by_oid.o \ + ../heimdal/lib/gssapi/mech/gss_inquire_names_for_mech.o \ +../heimdal/lib/gssapi/mech/gss_inquire_mechs_for_name.o \ +../heimdal/lib/gssapi/mech/gss_wrap_size_limit.o \ +../heimdal/lib/gssapi/mech/gss_names.o \ +../heimdal/lib/gssapi/mech/gss_verify.o \ +../heimdal/lib/gssapi/mech/gss_display_name.o \ +../heimdal/lib/gssapi/mech/gss_duplicate_oid.o \ +../heimdal/lib/gssapi/mech/gss_display_status.o \ +../heimdal/lib/gssapi/mech/gss_release_buffer.o \ +../heimdal/lib/gssapi/mech/gss_release_oid.o \ +../heimdal/lib/gssapi/mech/gss_test_oid_set_member.o \ +../heimdal/lib/gssapi/mech/gss_release_cred.o \ +../heimdal/lib/gssapi/mech/gss_set_sec_context_option.o \ +../heimdal/lib/gssapi/mech/gss_export_name.o \ +../heimdal/lib/gssapi/mech/gss_seal.o \ +../heimdal/lib/gssapi/mech/mech_switch.h \ +../heimdal/lib/gssapi/mech/gss_acquire_cred.o \ +../heimdal/lib/gssapi/mech/gss_unseal.o \ +../heimdal/lib/gssapi/mech/gss_verify_mic.o \ +../heimdal/lib/gssapi/mech/gss_accept_sec_context.o \ +../heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.o \ +../heimdal/lib/gssapi/mech/gss_indicate_mechs.o \ +../heimdal/lib/gssapi/mech/gss_delete_sec_context.o \ +../heimdal/lib/gssapi/mech/gss_sign.o \ +../heimdal/lib/gssapi/mech/gss_utils.o \ +../heimdal/lib/gssapi/mech/gss_init_sec_context.o \ +../heimdal/lib/gssapi/mech/gss_oid_equal.o \ +../heimdal/lib/gssapi/mech/gss_context_time.o \ +../heimdal/lib/gssapi/mech/gss_encapsulate_token.o \ +../heimdal/lib/gssapi/mech/gss_get_mic.o \ +../heimdal/lib/gssapi/mech/gss_import_sec_context.o \ +../heimdal/lib/gssapi/mech/gss_inquire_cred.o \ +../heimdal/lib/gssapi/mech/gss_wrap.o \ +../heimdal/lib/gssapi/mech/gss_import_name.o \ +../heimdal/lib/gssapi/mech/gss_duplicate_name.o \ +../heimdal/lib/gssapi/mech/gss_unwrap.o \ +../heimdal/lib/gssapi/mech/gss_export_sec_context.o \ +../heimdal/lib/gssapi/mech/gss_inquire_context.o \ +../heimdal/lib/gssapi/mech/gss_release_name.o \ +../heimdal/lib/gssapi/mech/gss_set_cred_option.o \ +../heimdal/lib/gssapi/mech/asn1_GSSAPIContextToken.o \ + ../heimdal/lib/gssapi/spnego/init_sec_context.o \ + ../heimdal/lib/gssapi/spnego/external.o \ + ../heimdal/lib/gssapi/spnego/compat.o \ + ../heimdal/lib/gssapi/spnego/context_stubs.o \ + ../heimdal/lib/gssapi/spnego/cred_stubs.o \ + ../heimdal/lib/gssapi/spnego/accept_sec_context.o \ + ../heimdal/lib/gssapi/spnego/asn1_ContextFlags.o \ + ../heimdal/lib/gssapi/spnego/asn1_MechType.o \ + ../heimdal/lib/gssapi/spnego/asn1_MechTypeList.o \ + ../heimdal/lib/gssapi/spnego/asn1_NegHints.o \ + ../heimdal/lib/gssapi/spnego/asn1_NegTokenInit.o \ + ../heimdal/lib/gssapi/spnego/asn1_NegTokenResp.o \ + ../heimdal/lib/gssapi/krb5/copy_ccache.o \ + ../heimdal/lib/gssapi/krb5/delete_sec_context.o \ + ../heimdal/lib/gssapi/krb5/init_sec_context.o \ + ../heimdal/lib/gssapi/krb5/context_time.o \ + ../heimdal/lib/gssapi/krb5/init.o \ + ../heimdal/lib/gssapi/krb5/address_to_krb5addr.o \ + ../heimdal/lib/gssapi/krb5/get_mic.o \ + ../heimdal/lib/gssapi/krb5/inquire_context.o \ + ../heimdal/lib/gssapi/krb5/add_cred.o \ + ../heimdal/lib/gssapi/krb5/inquire_cred.o \ + ../heimdal/lib/gssapi/krb5/inquire_cred_by_oid.o \ + ../heimdal/lib/gssapi/krb5/inquire_cred_by_mech.o \ + ../heimdal/lib/gssapi/krb5/inquire_mechs_for_name.o \ + ../heimdal/lib/gssapi/krb5/inquire_names_for_mech.o \ + ../heimdal/lib/gssapi/krb5/indicate_mechs.o \ + ../heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.o \ + ../heimdal/lib/gssapi/krb5/export_sec_context.o \ + ../heimdal/lib/gssapi/krb5/import_sec_context.o \ + ../heimdal/lib/gssapi/krb5/duplicate_name.o \ + ../heimdal/lib/gssapi/krb5/import_name.o \ + ../heimdal/lib/gssapi/krb5/compare_name.o \ + ../heimdal/lib/gssapi/krb5/export_name.o \ + ../heimdal/lib/gssapi/krb5/canonicalize_name.o \ + ../heimdal/lib/gssapi/krb5/unwrap.o \ + ../heimdal/lib/gssapi/krb5/wrap.o \ + ../heimdal/lib/gssapi/krb5/release_name.o \ + ../heimdal/lib/gssapi/krb5/cfx.o \ + ../heimdal/lib/gssapi/krb5/add_oid_set_member.o \ + ../heimdal/lib/gssapi/krb5/release_oid_set.o \ + ../heimdal/lib/gssapi/krb5/create_emtpy_oid_set.o \ + ../heimdal/lib/gssapi/krb5/8003.o \ + ../heimdal/lib/gssapi/krb5/arcfour.o \ + ../heimdal/lib/gssapi/krb5/encapsulate.o \ + ../heimdal/lib/gssapi/krb5/display_name.o \ + ../heimdal/lib/gssapi/krb5/sequence.o \ + ../heimdal/lib/gssapi/krb5/display_status.o \ + ../heimdal/lib/gssapi/krb5/release_buffer.o \ + ../heimdal/lib/gssapi/krb5/test_oid_set_member.o \ + ../heimdal/lib/gssapi/krb5/external.o \ + ../heimdal/lib/gssapi/krb5/compat.o \ + ../heimdal/lib/gssapi/krb5/acquire_cred.o \ + ../heimdal/lib/gssapi/krb5/release_cred.o \ + ../heimdal/lib/gssapi/krb5/set_cred_option.o \ + ../heimdal/lib/gssapi/krb5/decapsulate.o \ + ../heimdal/lib/gssapi/krb5/verify_mic.o \ + ../heimdal/lib/gssapi/krb5/accept_sec_context.o \ + ../heimdal/lib/gssapi/krb5/set_sec_context_option.o \ + ../heimdal/lib/gssapi/krb5/process_context_token.o +PRIVATE_DEPENDENCIES = HEIMDAL_KRB5 HEIMDAL_ROKEN HEIMDAL_DES HEIMDAL_ASN1 HEIMDAL_GLUE # End SUBSYSTEM HEIMDAL_GSSAPI ####################### @@ -202,8 +289,9 @@ OBJ_FILES = \ ../heimdal/lib/asn1/der_length.o \ ../heimdal/lib/asn1/der_copy.o \ ../heimdal/lib/asn1/der_cmp.o \ + ../heimdal/lib/asn1/extra.o \ + ../heimdal/lib/asn1/timegm.o \ ../heimdal/lib/asn1/asn1_AD_IF_RELEVANT.o \ - ../heimdal/lib/asn1/asn1_AD_KDCIssued.o \ ../heimdal/lib/asn1/asn1_APOptions.o \ ../heimdal/lib/asn1/asn1_AP_REP.o \ ../heimdal/lib/asn1/asn1_AP_REQ.o \ @@ -211,7 +299,7 @@ OBJ_FILES = \ ../heimdal/lib/asn1/asn1_AS_REQ.o \ ../heimdal/lib/asn1/asn1_Authenticator.o \ ../heimdal/lib/asn1/asn1_AuthorizationData.o \ - ../heimdal/lib/asn1/asn1_CBCParameter.o \ + ../heimdal/lib/asn1/asn1_AuthorizationDataElement.o \ ../heimdal/lib/asn1/asn1_CKSUMTYPE.o \ ../heimdal/lib/asn1/asn1_ChangePasswdDataMS.o \ ../heimdal/lib/asn1/asn1_Checksum.o \ @@ -251,15 +339,17 @@ OBJ_FILES = \ ../heimdal/lib/asn1/asn1_PA_DATA.o \ ../heimdal/lib/asn1/asn1_PA_ENC_TS_ENC.o \ ../heimdal/lib/asn1/asn1_PA_PAC_REQUEST.o \ + ../heimdal/lib/asn1/asn1_PA_S4U2Self.o \ ../heimdal/lib/asn1/asn1_Principal.o \ ../heimdal/lib/asn1/asn1_PrincipalName.o \ - ../heimdal/lib/asn1/asn1_RC2CBCParameter.o \ ../heimdal/lib/asn1/asn1_Realm.o \ ../heimdal/lib/asn1/asn1_TGS_REP.o \ ../heimdal/lib/asn1/asn1_TGS_REQ.o \ ../heimdal/lib/asn1/asn1_Ticket.o \ ../heimdal/lib/asn1/asn1_TicketFlags.o \ ../heimdal/lib/asn1/asn1_TransitedEncoding.o \ + ../heimdal/lib/asn1/asn1_KRB5SignedPathData.o \ + ../heimdal/lib/asn1/asn1_KRB5SignedPathPrincipals.o \ ../heimdal/lib/asn1/asn1_err.o \ ../heimdal/lib/asn1/asn1_krb5int32.o \ ../heimdal/lib/asn1/asn1_krb5uint32.o @@ -287,6 +377,8 @@ OBJ_FILES = \ ../heimdal/lib/des/ui.o \ ../heimdal/lib/des/evp.o \ ../heimdal/lib/des/pkcs5.o \ + ../heimdal/lib/des/rand.o \ + ../heimdal/lib/des/rand-unix.o \ ../heimdal/lib/des/hmac.o # End SUBSYSTEM HEIMDAL_DES ####################### @@ -294,19 +386,19 @@ OBJ_FILES = \ ####################### # Start SUBSYSTEM HEIMDAL_ROKEN_GAI_STRERROR [SUBSYSTEM::HEIMDAL_ROKEN_GAI_STRERROR] -CFLAGS = -Iheimdal_build -Iheimdal/lib/roken +CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper OBJ_FILES = ../heimdal/lib/roken/gai_strerror.o [SUBSYSTEM::HEIMDAL_ROKEN_INET_ATON] -CFLAGS = -Iheimdal_build -Iheimdal/lib/roken +CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper OBJ_FILES = ../heimdal/lib/roken/inet_aton.o [SUBSYSTEM::HEIMDAL_ROKEN_GETPROGNAME] -CFLAGS = -Iheimdal_build -Iheimdal/lib/roken +CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper OBJ_FILES = ../heimdal/lib/roken/getprogname.o -[SUBSYSTEM::HEIMDAL_ROKEN_GETPROGNAME_H] -CFLAGS = -Iheimdal_build -Iheimdal/lib/roken +[SUBSYSTEM::HEIMDAL_ROKEN_GETPROGNAME_H] +CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper OBJ_FILES = ../heimdal/lib/roken/getprogname.ho ####################### @@ -326,7 +418,7 @@ PRIVATE_DEPENDENCIES = EXT_SOCKET ####################### # Start SUBSYSTEM HEIMDAL_ROKEN [SUBSYSTEM::HEIMDAL_ROKEN] -CFLAGS = -Iheimdal_build -Iheimdal/lib/roken +CFLAGS = -Iheimdal_build -Iheimdal/lib/roken -Ilib/socket_wrapper OBJ_FILES = \ ../heimdal/lib/roken/base64.o \ ../heimdal/lib/roken/hex.o \ @@ -347,6 +439,7 @@ OBJ_FILES = \ ../heimdal/lib/roken/strsep.o \ ../heimdal/lib/roken/strupr.o \ ../heimdal/lib/roken/strpool.o \ + ../heimdal/lib/roken/estrdup.o \ replace.o PUBLIC_DEPENDENCIES = \ HEIMDAL_ROKEN_ADDRINFO \ @@ -363,7 +456,7 @@ PUBLIC_DEPENDENCIES = \ ####################### # Start SUBSYSTEM HEIMDAL_GLUE [SUBSYSTEM::HEIMDAL_GLUE] -CFLAGS = -Iheimdal_build -Iheimdal/lib/krb5 -Iheimdal/lib/asn1 -Iheimdal/lib/com_err +CFLAGS = -Iheimdal_build -Iheimdal/lib/krb5 -Iheimdal/lib/asn1 -Iheimdal/lib/com_err OBJ_FILES = glue.o PUBLIC_DEPENDENCIES = LIBNETIF # End SUBSYSTEM HEIMDAL_GLUE @@ -383,7 +476,7 @@ PRIVATE_DEPENDENCIES = HEIMDAL_ROKEN ####################### # Start SUBSYSTEM HEIMDAL_ASN1_COMPILE_LEX [SUBSYSTEM::HEIMDAL_ASN1_COMPILE_LEX] -CFLAGS = -Iheimdal_build -Iheimdal/lib/asn1 -Iheimdal/lib/roken +CFLAGS = -Iheimdal_build -Iheimdal/lib/asn1 -Iheimdal/lib/roken -Ilib/socket_wrapper OBJ_FILES = ../heimdal/lib/asn1/lex.ho # End SUBSYSTEM HEIMDAL_ASN1_COMPILE_LEX ####################### @@ -402,6 +495,7 @@ OBJ_FILES = \ ../heimdal/lib/asn1/gen_free.ho \ ../heimdal/lib/asn1/gen_glue.ho \ ../heimdal/lib/asn1/gen_length.ho \ + ../heimdal/lib/asn1/gen_seq.ho \ ../heimdal/lib/asn1/hash.ho \ ../heimdal/lib/asn1/parse.ho \ ../heimdal/lib/roken/emalloc.ho \ @@ -421,7 +515,7 @@ PRIVATE_DEPENDENCIES = HEIMDAL_ASN1_COMPILE_LEX HEIMDAL_ROKEN_GETPROGNAME_H ####################### # Start SUBSYSTEM HEIMDAL_COM_ERR_COMPILE_LEX [SUBSYSTEM::HEIMDAL_COM_ERR_COMPILE_LEX] -CFLAGS = -Iheimdal_build -Iheimdal/lib/com_err -Iheimdal/lib/roken +CFLAGS = -Iheimdal_build -Iheimdal/lib/com_err -Iheimdal/lib/roken -Ilib/socket_wrapper OBJ_FILES = ../heimdal/lib/com_err/lex.ho # End SUBSYSTEM HEIMDAL_COM_ERR_COMPILE_LEX ####################### @@ -444,8 +538,10 @@ PRIVATE_DEPENDENCIES = HEIMDAL_COM_ERR_COMPILE_LEX HEIMDAL_ROKEN_GETPROGNAME_H ####################### include perl_path_wrapper.sh asn1_deps.pl heimdal/lib/hdb/hdb.asn1 hdb_asn1| -include perl_path_wrapper.sh asn1_deps.pl heimdal/lib/gssapi/spnego.asn1 spnego_asn1| -include perl_path_wrapper.sh asn1_deps.pl heimdal/lib/asn1/k5.asn1 krb5_asn1 --encode-rfc1510-bit-string| +include perl_path_wrapper.sh asn1_deps.pl heimdal/lib/gssapi/spnego/spnego.asn1 spnego_asn1| +include perl_path_wrapper.sh asn1_deps.pl heimdal/lib/gssapi/mech/gssapi.asn1 gssapi_asn1| +include perl_path_wrapper.sh asn1_deps.pl heimdal/lib/asn1/k5.asn1 krb5_asn1 --encode-rfc1510-bit-string --sequence=KRB5SignedPathPrincipals --sequence=AuthorizationData| +include perl_path_wrapper.sh asn1_deps.pl heimdal/lib/asn1/digest.asn1 digest_asn1| include perl_path_wrapper.sh et_deps.pl heimdal/lib/asn1/asn1_err.et| include perl_path_wrapper.sh et_deps.pl heimdal/lib/hdb/hdb_err.et| diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c index 7359fe63c3..8fd69aecb1 100644 --- a/source4/kdc/hdb-ldb.c +++ b/source4/kdc/hdb-ldb.c @@ -462,7 +462,7 @@ static krb5_error_code LDB_lookup_principal(krb5_context context, struct ldb_con struct ldb_result *res = NULL; - ret = krb5_unparse_name_norealm(context, principal, &short_princ); + ret = krb5_unparse_name_flags(context, principal, KRB5_PRINCIPAL_UNPARSE_NO_REALM, &short_princ); if (ret != 0) { krb5_set_error_string(context, "LDB_lookup_principal: could not parse principal"); @@ -713,7 +713,9 @@ static krb5_error_code LDB_fetch_server(krb5_context context, HDB *db, struct ldb_dn *user_dn, *domain_dn; char *principal_string; - ret = krb5_unparse_name_norealm(context, principal, &principal_string); + ret = krb5_unparse_name_flags(context, principal, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, + &principal_string); if (ret != 0) { return ret; } diff --git a/source4/kdc/kdc.c b/source4/kdc/kdc.c index 5da6be6eca..7d6155e1c0 100644 --- a/source4/kdc/kdc.c +++ b/source4/kdc/kdc.c @@ -49,7 +49,8 @@ typedef BOOL (*kdc_process_fn_t)(struct kdc_server *kdc, DATA_BLOB *input, DATA_BLOB *reply, struct socket_address *peer_addr, - struct socket_address *my_addr); + struct socket_address *my_addr, + int datagram); /* hold information about one kdc socket */ struct kdc_socket { @@ -157,7 +158,8 @@ static void kdc_recv_handler(struct kdc_socket *kdc_socket) tmp_ctx, &blob, &reply, - src, my_addr); + src, my_addr, + 1 /* Datagram */); if (!ret) { talloc_free(tmp_ctx); return; @@ -240,7 +242,8 @@ static NTSTATUS kdc_tcp_recv(void *private, DATA_BLOB blob) &input, &reply, src_addr, - my_addr); + my_addr, + 0 /* Not datagram */); if (!ret) { talloc_free(tmp_ctx); return NT_STATUS_INTERNAL_ERROR; @@ -306,10 +309,12 @@ static BOOL kdc_process(struct kdc_server *kdc, DATA_BLOB *input, DATA_BLOB *reply, struct socket_address *peer_addr, - struct socket_address *my_addr) + struct socket_address *my_addr, + int datagram_reply) { int ret; krb5_data k5_reply; + krb5_data_zero(&k5_reply); DEBUG(10,("Received KDC packet of length %lu from %s:%d\n", (long)input->length - 4, peer_addr->addr, peer_addr->port)); @@ -319,13 +324,18 @@ static BOOL kdc_process(struct kdc_server *kdc, input->data, input->length, &k5_reply, peer_addr->addr, - peer_addr->sockaddr); + peer_addr->sockaddr, + datagram_reply); if (ret == -1) { *reply = data_blob(NULL, 0); return False; } - *reply = data_blob_talloc(mem_ctx, k5_reply.data, k5_reply.length); - krb5_data_free(&k5_reply); + if (k5_reply.length) { + *reply = data_blob_talloc(mem_ctx, k5_reply.data, k5_reply.length); + krb5_free_data_contents(kdc->smb_krb5_context->krb5_context, &k5_reply); + } else { + *reply = data_blob(NULL, 0); + } return True; } diff --git a/source4/kdc/kdc.h b/source4/kdc/kdc.h index f0d2479a25..9cd51f1d97 100644 --- a/source4/kdc/kdc.h +++ b/source4/kdc/kdc.h @@ -37,7 +37,8 @@ BOOL kpasswdd_process(struct kdc_server *kdc, DATA_BLOB *input, DATA_BLOB *reply, struct socket_address *peer_addr, - struct socket_address *my_addr); + struct socket_address *my_addr, + int datagram_reply); /* top level context structure for the kdc server diff --git a/source4/kdc/kpasswdd.c b/source4/kdc/kpasswdd.c index 0dcbf9833d..6bc10cdced 100644 --- a/source4/kdc/kpasswdd.c +++ b/source4/kdc/kpasswdd.c @@ -410,7 +410,8 @@ BOOL kpasswdd_process(struct kdc_server *kdc, DATA_BLOB *input, DATA_BLOB *reply, struct socket_address *peer_addr, - struct socket_address *my_addr) + struct socket_address *my_addr, + int datagram_reply) { BOOL ret; const uint16_t header_len = 6; diff --git a/source4/kdc/pac-glue.c b/source4/kdc/pac-glue.c index e80ad060ed..143690ff0d 100644 --- a/source4/kdc/pac-glue.c +++ b/source4/kdc/pac-glue.c @@ -32,7 +32,7 @@ struct krb5_dh_moduli; struct _krb5_krb_auth_data; -#include "heimdal/lib/krb5/krb5-private.h" +#include "heimdal/lib/krb5/krb5_locl.h" /* Given the right private pointer from hdb_ldb, get a PAC from the attached ldb messages */ static krb5_error_code samba_get_pac(krb5_context context, diff --git a/source4/smbd/process_single.c b/source4/smbd/process_single.c index b8708f9ebe..60e5b1f584 100644 --- a/source4/smbd/process_single.c +++ b/source4/smbd/process_single.c @@ -25,18 +25,11 @@ #include "includes.h" #include "smbd/process_model.h" -/* For sepecifiying event context to GSSAPI below */ -#include "system/kerberos.h" -#include "heimdal/lib/gssapi/gssapi_locl.h" - - /* called when the process model is selected */ static void single_model_init(struct event_context *ev) { - /* Hack to ensure that GSSAPI uses the right event context */ - gssapi_krb5_init_ev(ev); } /* diff --git a/source4/smbd/process_standard.c b/source4/smbd/process_standard.c index 1efdd3d0c4..ec774b92df 100644 --- a/source4/smbd/process_standard.c +++ b/source4/smbd/process_standard.c @@ -28,10 +28,6 @@ #include "lib/socket/socket.h" #include "smbd/process_model.h" -/* For specifiying event context to GSSAPI below */ -#include "system/kerberos.h" -#include "heimdal/lib/gssapi/gssapi_locl.h" - #include "param/secrets.h" #ifdef HAVE_SETPROCTITLE @@ -115,9 +111,6 @@ static void standard_accept_connection(struct event_context *ev, DEBUG(0,("standard_accept_connection: tdb_reopen_all failed.\n")); } - /* Hack to ensure that GSSAPI uses the right event context */ - gssapi_krb5_init_ev(ev2); - /* Ensure that the forked children do not expose identical random streams */ set_need_random_reseed(); diff --git a/source4/static_deps.mk b/source4/static_deps.mk index 3ee1c53100..96edd97e43 100644 --- a/source4/static_deps.mk +++ b/source4/static_deps.mk @@ -20,9 +20,11 @@ heimdal_basics: \ heimdal/lib/roken/vis.h \ heimdal/lib/roken/err.h \ heimdal/lib/hdb/hdb_asn1.h \ - heimdal/lib/gssapi/spnego_asn1.h \ + heimdal/lib/gssapi/spnego/spnego_asn1.h \ + heimdal/lib/gssapi/mech/gssapi_asn1.h \ heimdal/lib/asn1/krb5_asn1.h \ heimdal/lib/asn1/asn1_err.h \ + heimdal/lib/asn1/digest_asn1.h \ heimdal/lib/hdb/hdb_err.h \ heimdal/lib/krb5/heim_err.h \ heimdal/lib/krb5/k524_err.h \ diff --git a/source4/torture/auth/pac.c b/source4/torture/auth/pac.c index 629b573ec3..3c122c930b 100644 --- a/source4/torture/auth/pac.c +++ b/source4/torture/auth/pac.c @@ -97,14 +97,16 @@ static bool torture_pac_self_check(struct torture_context *tctx) torture_fail(tctx, "auth_anonymous_server_info"); } - ret = krb5_parse_name_norealm(smb_krb5_context->krb5_context, - server_info->account_name, &client_principal); + ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, + server_info->account_name, + KRB5_PRINCIPAL_PARSE_NO_REALM, + &client_principal); if (ret) { krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &server_keyblock); krb5_free_keyblock_contents(smb_krb5_context->krb5_context, &krbtgt_keyblock); - torture_fail(tctx, "krb5_parse_name_norealm"); + torture_fail(tctx, "krb5_parse_name_flags(norealm)"); } /* OK, go ahead and make a PAC */ |