/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * GSSAPI library stub module for gssd. */ #include #include #include #include "gssd.h" #include #ifdef _KERNEL #define MALLOC(n) kmem_alloc((n), KM_SLEEP) #define FREE(x, n) kmem_free((x), (n)) #define memcpy(dst, src, n) bcopy((src), (dst), (n)) #define clnt_pcreateerror(srv) printf("Cannot connect to server on %s\n", srv) #ifdef DEBUG #ifndef _SYS_CMN_ERR_H #define _SYS_CMN_ERR_H #define CE_NOTE 1 #endif #include #include #include #include #include #include #include #include #endif /* DEBUG */ #else /* !_KERNEL */ #define MALLOC(n) malloc(n) #define FREE(x, n) free(x) #endif /* _KERNEL */ #define DEFAULT_MINOR_STAT ((OM_uint32) ~0) CLIENT *clnt, *getgssd_handle(); char *server = "localhost"; OM_uint32 kgss_acquire_cred_wrapped(minor_status, desired_name, time_req, desired_mechs, cred_usage, output_cred_handle, actual_mechs, time_rec, uid, gssd_cred_verifier) OM_uint32 *minor_status; gss_name_t desired_name; OM_uint32 time_req; gss_OID_set desired_mechs; int cred_usage; gssd_cred_id_t *output_cred_handle; gss_OID_set *actual_mechs; OM_uint32 *time_rec; uid_t uid; OM_uint32 *gssd_cred_verifier; { OM_uint32 minor_status_temp; gss_buffer_desc external_name; gss_OID name_type; int i; gss_acquire_cred_arg arg; gss_acquire_cred_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* convert the desired name from internal to external format */ if (gss_display_name(&minor_status_temp, desired_name, &external_name, &name_type) != GSS_S_COMPLETE) { *minor_status = (OM_uint32) minor_status_temp; gss_release_buffer(&minor_status_temp, &external_name); return ((OM_uint32) GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32)uid; arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length; arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value; arg.name_type.GSS_OID_len = name_type == GSS_C_NULL_OID ? 0 : (uint_t)name_type->length; arg.name_type.GSS_OID_val = name_type == GSS_C_NULL_OID ? (char *)NULL : (char *)name_type->elements; arg.time_req = time_req; if (desired_mechs != GSS_C_NULL_OID_SET) { arg.desired_mechs.GSS_OID_SET_len = (uint_t)desired_mechs->count; arg.desired_mechs.GSS_OID_SET_val = (GSS_OID *) MALLOC(sizeof (GSS_OID) * desired_mechs->count); for (i = 0; i < desired_mechs->count; i++) { arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len = (uint_t)desired_mechs->elements[i].length; arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val = (char *) MALLOC(desired_mechs->elements[i].length); memcpy(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val, desired_mechs->elements[i].elements, desired_mechs->elements[i].length); } } else arg.desired_mechs.GSS_OID_SET_len = 0; arg.cred_usage = cred_usage; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_acquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (output_cred_handle != NULL) *output_cred_handle = 0; if (actual_mechs != NULL) *actual_mechs = NULL; if (time_rec != NULL) *time_rec = 0; return (GSS_S_FAILURE); } /* free the allocated memory for the flattened name and desire_mechs */ gss_release_buffer(&minor_status_temp, &external_name); for (i = 0; i < desired_mechs->count; i++) FREE(arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_val, arg.desired_mechs.GSS_OID_SET_val[i].GSS_OID_len); FREE(arg.desired_mechs.GSS_OID_SET_val, arg.desired_mechs.GSS_OID_SET_len * sizeof (GSS_OID)); /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (output_cred_handle != NULL) { *output_cred_handle = /*LINTED*/ *((gssd_cred_id_t *)res.output_cred_handle.GSS_CRED_ID_T_val); *gssd_cred_verifier = res.gssd_cred_verifier; } if (res.status == GSS_S_COMPLETE && res.actual_mechs.GSS_OID_SET_len != 0 && actual_mechs != NULL) { *actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); (*actual_mechs)->count = (int)res.actual_mechs.GSS_OID_SET_len; (*actual_mechs)->elements = (gss_OID) MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count); for (i = 0; i < (*actual_mechs)->count; i++) { (*actual_mechs)->elements[i].length = (OM_uint32) res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len; (*actual_mechs)->elements[i].elements = (void *) MALLOC((*actual_mechs)->elements[i].length); memcpy((*actual_mechs)->elements[i].elements, res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val, (*actual_mechs)->elements[i].length); } } else { if (res.status == GSS_S_COMPLETE && actual_mechs != NULL) (*actual_mechs)->count = 0; } if (time_rec != NULL) *time_rec = res.time_rec; /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_acquire_cred_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_acquire_cred(minor_status, desired_name, time_req, desired_mechs, cred_usage, output_cred_handle, actual_mechs, time_rec, uid) OM_uint32 *minor_status; gss_name_t desired_name; OM_uint32 time_req; gss_OID_set desired_mechs; int cred_usage; gss_cred_id_t *output_cred_handle; gss_OID_set *actual_mechs; OM_uint32 *time_rec; uid_t uid; { OM_uint32 err; struct kgss_cred *kcred; kcred = KGSS_CRED_ALLOC(); *output_cred_handle = (gss_cred_id_t)kcred; err = kgss_acquire_cred_wrapped(minor_status, desired_name, time_req, desired_mechs, cred_usage, &kcred->gssd_cred, actual_mechs, time_rec, uid, &kcred->gssd_cred_verifier); if (GSS_ERROR(err)) { KGSS_CRED_FREE(kcred); *output_cred_handle = GSS_C_NO_CREDENTIAL; } return (err); } OM_uint32 kgss_add_cred_wrapped(minor_status, input_cred_handle, gssd_cred_verifier, desired_name, desired_mech_type, cred_usage, initiator_time_req, acceptor_time_req, actual_mechs, initiator_time_rec, acceptor_time_rec, uid) OM_uint32 *minor_status; gssd_cred_id_t input_cred_handle; OM_uint32 gssd_cred_verifier; gss_name_t desired_name; gss_OID desired_mech_type; int cred_usage; int initiator_time_req; int acceptor_time_req; gss_OID_set *actual_mechs; OM_uint32 *initiator_time_rec; OM_uint32 *acceptor_time_rec; uid_t uid; { CLIENT *clnt; OM_uint32 minor_status_temp; gss_buffer_desc external_name; gss_OID name_type; int i; gss_add_cred_arg arg; gss_add_cred_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* convert the desired name from internal to external format */ if (gss_display_name(&minor_status_temp, desired_name, &external_name, &name_type) != GSS_S_COMPLETE) { *minor_status = (OM_uint32) minor_status_temp; (void) gss_release_buffer(&minor_status_temp, &external_name); clnt_pcreateerror(server); return ((OM_uint32) GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.input_cred_handle.GSS_CRED_ID_T_len = input_cred_handle == GSSD_NO_CREDENTIAL ? 0 : (uint_t)sizeof (gssd_cred_id_t); arg.input_cred_handle.GSS_CRED_ID_T_val = (char *)&input_cred_handle; arg.gssd_cred_verifier = gssd_cred_verifier; arg.desired_name.GSS_BUFFER_T_len = (uint_t)external_name.length; arg.desired_name.GSS_BUFFER_T_val = (char *)external_name.value; arg.name_type.GSS_OID_len = name_type == GSS_C_NULL_OID ? 0 : (uint_t)name_type->length; arg.name_type.GSS_OID_val = name_type == GSS_C_NULL_OID ? (char *)NULL : (char *)name_type->elements; arg.desired_mech_type.GSS_OID_len = (uint_t)(desired_mech_type != GSS_C_NULL_OID ? desired_mech_type->length : 0); arg.desired_mech_type.GSS_OID_val = (char *)(desired_mech_type != GSS_C_NULL_OID ? desired_mech_type->elements : 0); arg.cred_usage = cred_usage; arg.initiator_time_req = initiator_time_req; arg.acceptor_time_req = acceptor_time_req; /* call the remote procedure */ bzero((caddr_t)&res, sizeof (res)); if (gss_add_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return * GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (actual_mechs != NULL) *actual_mechs = NULL; if (initiator_time_rec != NULL) *initiator_time_rec = 0; if (acceptor_time_rec != NULL) *acceptor_time_rec = 0; return (GSS_S_FAILURE); } /* free the allocated memory for the flattened name */ (void) gss_release_buffer(&minor_status_temp, &external_name); /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (res.status == GSS_S_COMPLETE && res.actual_mechs.GSS_OID_SET_len != 0 && actual_mechs != NULL) { *actual_mechs = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); (*actual_mechs)->count = (int)res.actual_mechs.GSS_OID_SET_len; (*actual_mechs)->elements = (gss_OID) MALLOC(sizeof (gss_OID_desc) * (*actual_mechs)->count); for (i = 0; i < (*actual_mechs)->count; i++) { (*actual_mechs)->elements[i].length = (OM_uint32) res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_len; (*actual_mechs)->elements[i].elements = (void *) MALLOC((*actual_mechs)->elements[i].length); memcpy((*actual_mechs)->elements[i].elements, res.actual_mechs.GSS_OID_SET_val[i].GSS_OID_val, (*actual_mechs)->elements[i].length); } } else { if (res.status == GSS_S_COMPLETE && actual_mechs != NULL) (*actual_mechs)->count = 0; } if (initiator_time_rec != NULL) *initiator_time_rec = res.initiator_time_rec; if (acceptor_time_rec != NULL) *acceptor_time_rec = res.acceptor_time_rec; /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_add_cred_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_add_cred(minor_status, input_cred_handle, desired_name, desired_mech_type, cred_usage, initiator_time_req, acceptor_time_req, actual_mechs, initiator_time_rec, acceptor_time_rec, uid) OM_uint32 *minor_status; gss_cred_id_t input_cred_handle; gss_name_t desired_name; gss_OID desired_mech_type; int cred_usage; int initiator_time_req; int acceptor_time_req; gss_OID_set *actual_mechs; OM_uint32 *initiator_time_rec; OM_uint32 *acceptor_time_rec; uid_t uid; { OM_uint32 err; OM_uint32 gssd_cred_verifier; gssd_cred_id_t gssd_input_cred_handle; if (input_cred_handle != GSS_C_NO_CREDENTIAL) { gssd_cred_verifier = KCRED_TO_CREDV(input_cred_handle); gssd_input_cred_handle = KCRED_TO_CRED(input_cred_handle); } else gssd_input_cred_handle = GSSD_NO_CREDENTIAL; err = kgss_add_cred_wrapped(minor_status, gssd_input_cred_handle, gssd_cred_verifier, desired_name, desired_mech_type, cred_usage, initiator_time_req, acceptor_time_req, actual_mechs, initiator_time_rec, acceptor_time_rec, uid); return (err); } OM_uint32 kgss_release_cred_wrapped(minor_status, cred_handle, uid, gssd_cred_verifier) OM_uint32 *minor_status; gssd_cred_id_t *cred_handle; uid_t uid; OM_uint32 gssd_cred_verifier; { gss_release_cred_arg arg; gss_release_cred_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.gssd_cred_verifier = gssd_cred_verifier; if (cred_handle != NULL) { arg.cred_handle.GSS_CRED_ID_T_len = (uint_t)sizeof (gssd_cred_id_t); arg.cred_handle.GSS_CRED_ID_T_val = (char *)cred_handle; } else arg.cred_handle.GSS_CRED_ID_T_len = 0; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_release_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its max value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (cred_handle != NULL) *cred_handle = 0; return (GSS_S_FAILURE); } /* if the release succeeded, null out the cred_handle */ if (res.status == GSS_S_COMPLETE && cred_handle != NULL) *cred_handle = 0; /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; /* return with status returned in rpc call */ return (res.status); } OM_uint32 kgss_release_cred(minor_status, cred_handle, uid) OM_uint32 *minor_status; gss_cred_id_t *cred_handle; uid_t uid; { OM_uint32 err; struct kgss_cred *kcred; if (*cred_handle == GSS_C_NO_CREDENTIAL) return (GSS_S_COMPLETE); else kcred = KCRED_TO_KGSS_CRED(*cred_handle); err = kgss_release_cred_wrapped(minor_status, &kcred->gssd_cred, uid, kcred->gssd_cred_verifier); KGSS_CRED_FREE(kcred); *cred_handle = GSS_C_NO_CREDENTIAL; return (err); } OM_uint32 kgss_init_sec_context_wrapped(minor_status, claimant_cred_handle, gssd_cred_verifier, context_handle, gssd_context_verifier, target_name, mech_type, req_flags, time_req, input_chan_bindings, input_token, actual_mech_type, output_token, ret_flags, time_rec, uid) OM_uint32 *minor_status; gssd_cred_id_t claimant_cred_handle; OM_uint32 gssd_cred_verifier; OM_uint32 *context_handle; OM_uint32 *gssd_context_verifier; gss_name_t target_name; gss_OID mech_type; int req_flags; OM_uint32 time_req; gss_channel_bindings_t input_chan_bindings; gss_buffer_t input_token; gss_OID *actual_mech_type; gss_buffer_t output_token; int *ret_flags; OM_uint32 *time_rec; uid_t uid; { OM_uint32 minor_status_temp; gss_buffer_desc external_name; gss_OID name_type; gss_init_sec_context_arg arg; gss_init_sec_context_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* convert the target name from internal to external format */ if (gss_display_name(&minor_status_temp, target_name, &external_name, &name_type) != GSS_S_COMPLETE) { *minor_status = (OM_uint32) minor_status_temp; return ((OM_uint32) GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.context_handle.GSS_CTX_ID_T_len = *context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 : (uint_t)sizeof (OM_uint32); arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; arg.gssd_context_verifier = *gssd_context_verifier; arg.claimant_cred_handle.GSS_CRED_ID_T_len = claimant_cred_handle == GSSD_NO_CREDENTIAL ? 0 : (uint_t)sizeof (gssd_cred_id_t); arg.claimant_cred_handle.GSS_CRED_ID_T_val = (char *)&claimant_cred_handle; arg.gssd_cred_verifier = gssd_cred_verifier; arg.target_name.GSS_BUFFER_T_len = (uint_t)external_name.length; arg.target_name.GSS_BUFFER_T_val = (char *)external_name.value; arg.name_type.GSS_OID_len = name_type == GSS_C_NULL_OID ? 0 : (uint_t)name_type->length; arg.name_type.GSS_OID_val = name_type == GSS_C_NULL_OID ? (char *)NULL : (char *)name_type->elements; arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ? mech_type->length : 0); arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ? mech_type->elements : 0); arg.req_flags = req_flags; arg.time_req = time_req; if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) { arg.input_chan_bindings.present = YES; arg.input_chan_bindings.initiator_addrtype = input_chan_bindings->initiator_addrtype; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->initiator_address.length; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = (void *) input_chan_bindings->initiator_address.value; arg.input_chan_bindings.acceptor_addrtype = input_chan_bindings->acceptor_addrtype; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->acceptor_address.length; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = (void *) input_chan_bindings->acceptor_address.value; arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->application_data.length; arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = (void *) input_chan_bindings->application_data.value; } else { arg.input_chan_bindings.present = NO; arg.input_chan_bindings.initiator_addrtype = 0; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0; arg.input_chan_bindings.acceptor_addrtype = 0; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0; arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0; } arg.input_token.GSS_BUFFER_T_len = (uint_t) (input_token != GSS_C_NO_BUFFER ? input_token->length : 0); arg.input_token.GSS_BUFFER_T_val = (char *) (input_token != GSS_C_NO_BUFFER ? input_token->value : 0); /* initialize the output parameters to empty values */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (actual_mech_type != NULL) *actual_mech_type = NULL; if (output_token != NULL) output_token->length = 0; if (ret_flags != NULL) *ret_flags = 0; if (time_rec != NULL) *time_rec = 0; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_init_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { /* free the allocated memory for the flattened name */ gss_release_buffer(&minor_status_temp, &external_name); return (GSS_S_FAILURE); } /* * We could return from a GSS error here and need to return both the * minor_status and output_token, back to the caller if applicable. */ if (minor_status != NULL) *minor_status = res.minor_status; if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) { output_token->length = (size_t)res.output_token.GSS_BUFFER_T_len; output_token->value = (void *)res.output_token.GSS_BUFFER_T_val; res.output_token.GSS_BUFFER_T_val = NULL; res.output_token.GSS_BUFFER_T_len = 0; } /* free the allocated memory for the flattened name */ gss_release_buffer(&minor_status_temp, &external_name); /* if the call was successful, copy out the results */ if (res.status == (OM_uint32) GSS_S_COMPLETE || res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) { /* * copy the rpc results into the return argument * on CONTINUE_NEEDED only ctx handle is ready. */ /*LINTED*/ *context_handle = *((OM_uint32 *) res.context_handle.GSS_CTX_ID_T_val); *gssd_context_verifier = res.gssd_context_verifier; /* the rest of the parameters is only ready on COMPLETE */ if (res.status == GSS_S_COMPLETE) { if (actual_mech_type != NULL) { *actual_mech_type = (gss_OID) MALLOC(sizeof (gss_OID_desc)); (*actual_mech_type)->length = (OM_UINT32) res.actual_mech_type.GSS_OID_len; (*actual_mech_type)->elements = (void *) MALLOC((*actual_mech_type)->length); memcpy((*actual_mech_type)->elements, (void *) res.actual_mech_type.GSS_OID_val, (*actual_mech_type)->length); } if (ret_flags != NULL) *ret_flags = res.ret_flags; if (time_rec != NULL) *time_rec = res.time_rec; } } /* * free the memory allocated for the results and return with the * status received in the rpc call. */ clnt_freeres(clnt, xdr_gss_init_sec_context_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_init_sec_context( OM_uint32 *minor_status, gss_cred_id_t claimant_cred_handle, gss_ctx_id_t *context_handle, gss_name_t target_name, gss_OID mech_type, int req_flags, OM_uint32 time_req, gss_channel_bindings_t input_chan_bindings, gss_buffer_t input_token, gss_OID *actual_mech_type, gss_buffer_t output_token, int *ret_flags, OM_uint32 *time_rec, uid_t uid) { OM_uint32 err; struct kgss_ctx *kctx; OM_uint32 gssd_cred_verifier; gssd_cred_id_t gssd_cl_cred_handle; /* * If this is an initial call, we'll need to create the * wrapper struct that contains kernel state information, and * a reference to the handle from gssd. */ if (*context_handle == GSS_C_NO_CONTEXT) { kctx = KGSS_ALLOC(); *context_handle = (gss_ctx_id_t)kctx; kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT; } else kctx = (struct kgss_ctx *)*context_handle; if (claimant_cred_handle != GSS_C_NO_CREDENTIAL) { gssd_cred_verifier = KCRED_TO_CREDV(claimant_cred_handle); gssd_cl_cred_handle = KCRED_TO_CRED(claimant_cred_handle); } else { gssd_cl_cred_handle = GSSD_NO_CREDENTIAL; } err = kgss_init_sec_context_wrapped(minor_status, gssd_cl_cred_handle, gssd_cred_verifier, &kctx->gssd_ctx, &kctx->gssd_ctx_verifier, target_name, mech_type, req_flags, time_req, input_chan_bindings, input_token, actual_mech_type, output_token, ret_flags, time_rec, uid); if (GSS_ERROR(err)) { KGSS_FREE(kctx); *context_handle = GSS_C_NO_CONTEXT; } return (err); } OM_uint32 kgss_accept_sec_context_wrapped(minor_status, context_handle, gssd_context_verifier, verifier_cred_handle, gssd_cred_verifier, input_token, input_chan_bindings, src_name, mech_type, output_token, ret_flags, time_rec, delegated_cred_handle, uid) OM_uint32 *minor_status; gssd_ctx_id_t *context_handle; OM_uint32 *gssd_context_verifier; gssd_cred_id_t verifier_cred_handle; OM_uint32 gssd_cred_verifier; gss_buffer_t input_token; gss_channel_bindings_t input_chan_bindings; gss_buffer_t src_name; gss_OID *mech_type; gss_buffer_t output_token; int *ret_flags; OM_uint32 *time_rec; gss_cred_id_t *delegated_cred_handle; uid_t uid; { gss_accept_sec_context_arg arg; gss_accept_sec_context_res res; struct kgss_cred *kcred; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.context_handle.GSS_CTX_ID_T_len = *context_handle == GSSD_NO_CONTEXT ? 0 : (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; arg.gssd_context_verifier = *context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 : *gssd_context_verifier; arg.verifier_cred_handle.GSS_CRED_ID_T_len = verifier_cred_handle == GSSD_NO_CREDENTIAL ? 0 : (uint_t)sizeof (gssd_cred_id_t); arg.verifier_cred_handle.GSS_CRED_ID_T_val = (char *)&verifier_cred_handle; arg.gssd_cred_verifier = gssd_cred_verifier; arg.input_token_buffer.GSS_BUFFER_T_len = (uint_t)(input_token != GSS_C_NO_BUFFER ? input_token->length : 0); arg.input_token_buffer.GSS_BUFFER_T_val = (char *)(input_token != GSS_C_NO_BUFFER ? input_token->value : 0); if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) { arg.input_chan_bindings.present = YES; arg.input_chan_bindings.initiator_addrtype = input_chan_bindings->initiator_addrtype; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->initiator_address.length; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = (void *) input_chan_bindings->initiator_address.value; arg.input_chan_bindings.acceptor_addrtype = input_chan_bindings->acceptor_addrtype; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->acceptor_address.length; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = (void *) input_chan_bindings->acceptor_address.value; arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = (uint_t)input_chan_bindings->application_data.length; arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = (void *) input_chan_bindings->application_data.value; } else { arg.input_chan_bindings.present = NO; arg.input_chan_bindings.initiator_addrtype = 0; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.initiator_address.GSS_BUFFER_T_val = 0; arg.input_chan_bindings.acceptor_addrtype = 0; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.acceptor_address.GSS_BUFFER_T_val = 0; arg.input_chan_bindings.application_data.GSS_BUFFER_T_len = 0; arg.input_chan_bindings.application_data.GSS_BUFFER_T_val = 0; } /* set the output parameters to empty values.... */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (src_name != NULL) { src_name->length = 0; src_name->value = NULL; } if (mech_type != NULL) *mech_type = NULL; if (output_token != NULL) output_token->length = 0; if (ret_flags != NULL) *ret_flags = 0; if (time_rec != NULL) *time_rec = 0; if (delegated_cred_handle != NULL) *delegated_cred_handle = NULL; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_accept_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { return (GSS_S_FAILURE); } /* * We could return from a GSS error here and need to return both the * minor_status and output_token, back to the caller if applicable. */ if (minor_status != NULL) *minor_status = res.minor_status; if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) { output_token->length = res.output_token.GSS_BUFFER_T_len; output_token->value = (void *) res.output_token.GSS_BUFFER_T_val; res.output_token.GSS_BUFFER_T_val = 0; res.output_token.GSS_BUFFER_T_len = 0; } if (res.status == (OM_uint32) GSS_S_COMPLETE || res.status == (OM_uint32) GSS_S_CONTINUE_NEEDED) { /* * when gss returns CONTINUE_NEEDED we can only * use the context parameter. */ /*LINTED*/ *context_handle = *((gssd_ctx_id_t *) res.context_handle.GSS_CTX_ID_T_val); *gssd_context_verifier = res.gssd_context_verifier; /* the other parameters are ready on for COMPLETE */ if (res.status == GSS_S_COMPLETE) { /* * The src_name is in external format. */ if (src_name != NULL) { src_name->length = res.src_name.GSS_BUFFER_T_len; src_name->value = res.src_name.GSS_BUFFER_T_val; res.src_name.GSS_BUFFER_T_val = NULL; res.src_name.GSS_BUFFER_T_len = 0; } /* * move mech type returned to mech_type * for gss_import_name_for_mech() */ if (mech_type != NULL) { *mech_type = (gss_OID) MALLOC(sizeof (gss_OID_desc)); (*mech_type)->length = (OM_UINT32) res.mech_type.GSS_OID_len; (*mech_type)->elements = (void *) MALLOC((*mech_type)->length); memcpy((*mech_type)->elements, res.mech_type.GSS_OID_val, (*mech_type)->length); } if (ret_flags != NULL) *ret_flags = res.ret_flags; if (time_rec != NULL) *time_rec = res.time_rec; if ((delegated_cred_handle != NULL) && (res.delegated_cred_handle.GSS_CRED_ID_T_len != 0)) { kcred = KGSS_CRED_ALLOC(); /*LINTED*/ kcred->gssd_cred = *((gssd_cred_id_t *) res.delegated_cred_handle.GSS_CRED_ID_T_val); kcred->gssd_cred_verifier = res.gssd_context_verifier; *delegated_cred_handle = (gss_cred_id_t)kcred; } } /* res.status == GSS_S_COMPLETE */ } /* res.status == GSS_S_COMPLETE or GSS_CONTINUE_NEEDED */ /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_accept_sec_context_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_accept_sec_context( OM_uint32 *minor_status, gss_ctx_id_t *context_handle, gss_cred_id_t verifier_cred_handle, gss_buffer_t input_token, gss_channel_bindings_t input_chan_bindings, gss_buffer_t src_name, gss_OID *mech_type, gss_buffer_t output_token, int *ret_flags, OM_uint32 *time_rec, gss_cred_id_t *delegated_cred_handle, uid_t uid) { OM_uint32 err; struct kgss_ctx *kctx; OM_uint32 gssd_cred_verifier; gssd_cred_id_t gssd_ver_cred_handle; if (*context_handle == GSS_C_NO_CONTEXT) { kctx = KGSS_ALLOC(); *context_handle = (gss_ctx_id_t)kctx; kctx->gssd_ctx = GSSD_NO_CONTEXT; } else kctx = (struct kgss_ctx *)*context_handle; if (verifier_cred_handle != GSS_C_NO_CREDENTIAL) { gssd_cred_verifier = KCRED_TO_CREDV(verifier_cred_handle); gssd_ver_cred_handle = KCRED_TO_CRED(verifier_cred_handle); } else gssd_ver_cred_handle = GSSD_NO_CREDENTIAL; err = kgss_accept_sec_context_wrapped(minor_status, &kctx->gssd_ctx, &kctx->gssd_ctx_verifier, gssd_ver_cred_handle, gssd_cred_verifier, input_token, input_chan_bindings, src_name, mech_type, output_token, ret_flags, time_rec, delegated_cred_handle, uid); if (GSS_ERROR(err)) { KGSS_FREE(kctx); *context_handle = GSS_C_NO_CONTEXT; } return (err); } OM_uint32 kgss_process_context_token(minor_status, context_handle, token_buffer, uid) OM_uint32 *minor_status; gss_ctx_id_t context_handle; gss_buffer_t token_buffer; uid_t uid; { OM_uint32 gssd_context_verifier; gss_process_context_token_arg arg; gss_process_context_token_res res; gssd_context_verifier = KGSS_CTX_TO_GSSD_CTXV(context_handle); /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gss_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.gssd_context_verifier = gssd_context_verifier; arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer; arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_process_context_token_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; /* return with status returned in rpc call */ return (res.status); } OM_uint32 kgss_delete_sec_context_wrapped(minor_status, context_handle, gssd_context_verifier, output_token) OM_uint32 *minor_status; gssd_ctx_id_t *context_handle; OM_uint32 gssd_context_verifier; gss_buffer_t output_token; { gss_delete_sec_context_arg arg; gss_delete_sec_context_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = *context_handle == (OM_uint32) GSS_C_NO_CONTEXT ? 0 : (uint_t)sizeof (OM_uint32); arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; arg.gssd_context_verifier = gssd_context_verifier; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_delete_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its max value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (context_handle != NULL) *context_handle = 0; if (output_token != NULL) output_token->length = 0; return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (res.context_handle.GSS_CTX_ID_T_len == 0) *context_handle = 0; else /*LINTED*/ *context_handle = *((gssd_ctx_id_t *) res.context_handle.GSS_CTX_ID_T_val); if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) { output_token->length = res.output_token.GSS_BUFFER_T_len; output_token->value = res.output_token.GSS_BUFFER_T_val; res.output_token.GSS_BUFFER_T_len = 0; res.output_token.GSS_BUFFER_T_val = NULL; } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_delete_sec_context_res, (caddr_t)&res); return (res.status); } /*ARGSUSED*/ OM_uint32 kgss_delete_sec_context( OM_uint32 *minor_status, gss_ctx_id_t *context_handle, gss_buffer_t output_token) { OM_uint32 err; struct kgss_ctx *kctx; if (*context_handle == GSS_C_NO_CONTEXT) { return (GSS_S_NO_CONTEXT); } else kctx = KCTX_TO_KGSS_CTX(*context_handle); err = kgss_delete_sec_context_wrapped(minor_status, &kctx->gssd_ctx, kctx->gssd_ctx_verifier, output_token); if (kctx->gssd_ctx != GSSD_NO_CONTEXT) err = GSS_S_FAILURE; else err = GSS_S_COMPLETE; KGSS_FREE(kctx); *context_handle = GSS_C_NO_CONTEXT; return (err); } /*ARGSUSED*/ OM_uint32 kgss_context_time(minor_status, context_handle, time_rec, uid) OM_uint32 *minor_status; gss_ctx_id_t context_handle; OM_uint32 *time_rec; uid_t uid; { return (GSS_S_FAILURE); } OM_uint32 kgss_sign_wrapped(minor_status, context_handle, qop_req, message_buffer, msg_token, gssd_context_verifier) OM_uint32 *minor_status; gssd_ctx_id_t context_handle; OM_uint32 gssd_context_verifier; int qop_req; gss_buffer_t message_buffer; gss_buffer_t msg_token; { gss_sign_arg arg; gss_sign_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.gssd_context_verifier = gssd_context_verifier; arg.qop_req = qop_req; arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length; arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_sign_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (msg_token != NULL) msg_token->length = 0; return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (msg_token != NULL) { msg_token->length = res.msg_token.GSS_BUFFER_T_len; msg_token->value = (void *) MALLOC(msg_token->length); memcpy(msg_token->value, res.msg_token.GSS_BUFFER_T_val, msg_token->length); } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_sign_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_sign( OM_uint32 *minor_status, gss_ctx_id_t context_handle, int qop_req, gss_buffer_t message_buffer, gss_buffer_t msg_token) { if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_FAILURE); return (KGSS_SIGN(minor_status, context_handle, qop_req, message_buffer, msg_token)); } OM_uint32 kgss_verify_wrapped( minor_status, context_handle, message_buffer, token_buffer, qop_state, gssd_context_verifier) OM_uint32 *minor_status; gssd_ctx_id_t context_handle; OM_uint32 gssd_context_verifier; gss_buffer_t message_buffer; gss_buffer_t token_buffer; int *qop_state; { gss_verify_arg arg; gss_verify_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.gssd_context_verifier = gssd_context_verifier; arg.message_buffer.GSS_BUFFER_T_len = (uint_t)message_buffer->length; arg.message_buffer.GSS_BUFFER_T_val = (char *)message_buffer->value; arg.token_buffer.GSS_BUFFER_T_len = (uint_t)token_buffer->length; arg.token_buffer.GSS_BUFFER_T_val = (char *)token_buffer->value; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_verify_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (qop_state != NULL) *qop_state = 0; return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (qop_state != NULL) *qop_state = res.qop_state; /* return with status returned in rpc call */ return (res.status); } OM_uint32 kgss_verify(OM_uint32 *minor_status, gss_ctx_id_t context_handle, gss_buffer_t message_buffer, gss_buffer_t token_buffer, int *qop_state) { if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_FAILURE); return (KGSS_VERIFY(minor_status, context_handle, message_buffer, token_buffer, qop_state)); } OM_uint32 kgss_seal_wrapped( minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer, gssd_context_verifier) OM_uint32 *minor_status; gssd_ctx_id_t context_handle; OM_uint32 gssd_context_verifier; int conf_req_flag; int qop_req; gss_buffer_t input_message_buffer; int *conf_state; gss_buffer_t output_message_buffer; { gss_seal_arg arg; gss_seal_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.gssd_context_verifier = gssd_context_verifier; arg.conf_req_flag = conf_req_flag; arg.qop_req = qop_req; arg.input_message_buffer.GSS_BUFFER_T_len = (uint_t)input_message_buffer->length; arg.input_message_buffer.GSS_BUFFER_T_val = (char *)input_message_buffer->value; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_seal_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (conf_state != NULL) *conf_state = 0; if (output_message_buffer != NULL) output_message_buffer->length = 0; return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (conf_state != NULL) *conf_state = res.conf_state; if (output_message_buffer != NULL) { output_message_buffer->length = res.output_message_buffer.GSS_BUFFER_T_len; output_message_buffer->value = (void *) MALLOC(output_message_buffer->length); memcpy(output_message_buffer->value, res.output_message_buffer.GSS_BUFFER_T_val, output_message_buffer->length); } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_seal_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_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) { if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_FAILURE); return (KGSS_SEAL(minor_status, context_handle, conf_req_flag, qop_req, input_message_buffer, conf_state, output_message_buffer)); } OM_uint32 kgss_unseal_wrapped(minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, qop_state, gssd_context_verifier) OM_uint32 *minor_status; gssd_ctx_id_t context_handle; OM_uint32 gssd_context_verifier; gss_buffer_t input_message_buffer; gss_buffer_t output_message_buffer; int *conf_state; int *qop_state; { gss_unseal_arg arg; gss_unseal_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)&context_handle; arg.gssd_context_verifier = gssd_context_verifier; arg.input_message_buffer.GSS_BUFFER_T_len = (uint_t)input_message_buffer->length; arg.input_message_buffer.GSS_BUFFER_T_val = (char *)input_message_buffer->value; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_unseal_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (output_message_buffer != NULL) output_message_buffer->length = 0; if (conf_state != NULL) *conf_state = 0; if (qop_state != NULL) *qop_state = 0; return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (output_message_buffer != NULL) { output_message_buffer->length = res.output_message_buffer.GSS_BUFFER_T_len; output_message_buffer->value = (void *) MALLOC(output_message_buffer->length); memcpy(output_message_buffer->value, res.output_message_buffer.GSS_BUFFER_T_val, output_message_buffer->length); } if (conf_state != NULL) *conf_state = res.conf_state; if (qop_state != NULL) *qop_state = res.qop_state; /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_unseal_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_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) { if (context_handle == GSS_C_NO_CONTEXT) return (GSS_S_FAILURE); return (KGSS_UNSEAL(minor_status, context_handle, input_message_buffer, output_message_buffer, conf_state, qop_state)); } OM_uint32 kgss_display_status(minor_status, status_value, status_type, mech_type, message_context, status_string, uid) OM_uint32 *minor_status; OM_uint32 status_value; int status_type; gss_OID mech_type; int *message_context; gss_buffer_t status_string; uid_t uid; { gss_display_status_arg arg; gss_display_status_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.status_value = status_value; arg.status_type = status_type; arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ? mech_type->length : 0); arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ? mech_type->elements : 0); arg.message_context = *message_context; /* call the remote procedure */ if (message_context != NULL) *message_context = 0; if (status_string != NULL) { status_string->length = 0; status_string->value = NULL; } memset(&res, 0, sizeof (res)); if (gss_display_status_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; return (GSS_S_FAILURE); } if (minor_status != NULL) *minor_status = res.minor_status; /* now process the results and pass them back to the caller */ if (res.status == GSS_S_COMPLETE) { if (message_context != NULL) *message_context = res.message_context; if (status_string != NULL) { status_string->length = (size_t)res.status_string.GSS_BUFFER_T_len; status_string->value = (void *)MALLOC(status_string->length); memcpy(status_string->value, res.status_string.GSS_BUFFER_T_val, status_string->length); } } clnt_freeres(clnt, xdr_gss_display_status_res, (caddr_t)&res); return (res.status); } /*ARGSUSED*/ OM_uint32 kgss_indicate_mechs(minor_status, mech_set, uid) OM_uint32 *minor_status; gss_OID_set *mech_set; uid_t uid; { void *arg; gss_indicate_mechs_res res; int i; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } memset(&res, 0, sizeof (res)); if (gss_indicate_mechs_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (mech_set != NULL) *mech_set = NULL; return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (mech_set != NULL) { *mech_set = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); (*mech_set)->count = res.mech_set.GSS_OID_SET_len; (*mech_set)->elements = (void *) MALLOC ((*mech_set)->count * sizeof (gss_OID_desc)); for (i = 0; i < (*mech_set)->count; i++) { (*mech_set)->elements[i].length = res.mech_set.GSS_OID_SET_val[i].GSS_OID_len; (*mech_set)->elements[i].elements = (void *) MALLOC ((*mech_set)->elements[i].length); memcpy ((*mech_set)->elements[i].elements, res.mech_set.GSS_OID_SET_val[i].GSS_OID_val, (*mech_set)->elements[i].length); } } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_indicate_mechs_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_inquire_cred_wrapped(minor_status, cred_handle, gssd_cred_verifier, name, lifetime, cred_usage, mechanisms, uid) OM_uint32 *minor_status; gssd_cred_id_t cred_handle; OM_uint32 gssd_cred_verifier; gss_name_t *name; OM_uint32 *lifetime; int *cred_usage; gss_OID_set *mechanisms; uid_t uid; { OM_uint32 minor_status_temp; gss_buffer_desc external_name; gss_OID name_type; int i; gss_inquire_cred_arg arg; gss_inquire_cred_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.cred_handle.GSS_CRED_ID_T_len = cred_handle == GSSD_NO_CREDENTIAL ? 0 : (uint_t)sizeof (gssd_cred_id_t); arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle; arg.gssd_cred_verifier = gssd_cred_verifier; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_inquire_cred_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (name != NULL) *name = NULL; if (lifetime != NULL) *lifetime = 0; if (cred_usage != NULL) *cred_usage = 0; if (mechanisms != NULL) *mechanisms = NULL; return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; /* convert name from external to internal format */ if (name != NULL) { external_name.length = res.name.GSS_BUFFER_T_len; external_name.value = res.name.GSS_BUFFER_T_val; /* * we have to allocate a name_type descriptor and * elements storage, since gss_import_name() only * stores a pointer to the name_type info in the * union_name struct */ name_type = (gss_OID) MALLOC(sizeof (gss_OID_desc)); name_type->length = res.name_type.GSS_OID_len; name_type->elements = (void *) MALLOC(name_type->length); memcpy(name_type->elements, res.name_type.GSS_OID_val, name_type->length); if (gss_import_name(&minor_status_temp, &external_name, name_type, name) != GSS_S_COMPLETE) { *minor_status = (OM_uint32) minor_status_temp; gss_release_buffer(&minor_status_temp, &external_name); clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res); return ((OM_uint32) GSS_S_FAILURE); } } if (lifetime != NULL) *lifetime = res.lifetime; if (cred_usage != NULL) *cred_usage = res.cred_usage; if (mechanisms != NULL) { *mechanisms = (gss_OID_set) MALLOC(sizeof (gss_OID_set_desc)); if (res.mechanisms.GSS_OID_SET_len != 0) { (*mechanisms)->count = (int)res.mechanisms.GSS_OID_SET_len; (*mechanisms)->elements = (gss_OID) MALLOC(sizeof (gss_OID) * (*mechanisms)->count); for (i = 0; i < (*mechanisms)->count; i++) { (*mechanisms)->elements[i].length = (OM_uint32) res.mechanisms.GSS_OID_SET_val[i].GSS_OID_len; (*mechanisms)->elements[i].elements = (void *) MALLOC((*mechanisms)->elements[i].length); memcpy((*mechanisms)->elements[i].elements, res.mechanisms.GSS_OID_SET_val[i].GSS_OID_val, (*mechanisms)->elements[i].length); } } else (*mechanisms)->count = 0; } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_inquire_cred_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_inquire_cred(minor_status, cred_handle, name, lifetime, cred_usage, mechanisms, uid) OM_uint32 *minor_status; gss_cred_id_t cred_handle; gss_name_t *name; OM_uint32 *lifetime; int *cred_usage; gss_OID_set * mechanisms; uid_t uid; { OM_uint32 gssd_cred_verifier; gssd_cred_id_t gssd_cred_handle; gssd_cred_verifier = KCRED_TO_CREDV(cred_handle); gssd_cred_handle = KCRED_TO_CRED(cred_handle); return (kgss_inquire_cred_wrapped(minor_status, gssd_cred_handle, gssd_cred_verifier, name, lifetime, cred_usage, mechanisms, uid)); } OM_uint32 kgss_inquire_cred_by_mech_wrapped(minor_status, cred_handle, gssd_cred_verifier, mech_type, uid) OM_uint32 *minor_status; gssd_cred_id_t cred_handle; OM_uint32 gssd_cred_verifier; gss_OID mech_type; uid_t uid; { OM_uint32 minor_status_temp; gss_inquire_cred_by_mech_arg arg; gss_inquire_cred_by_mech_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.uid = (OM_uint32) uid; arg.cred_handle.GSS_CRED_ID_T_len = cred_handle == GSSD_NO_CREDENTIAL ? 0 : (uint_t)sizeof (gssd_cred_id_t); arg.cred_handle.GSS_CRED_ID_T_val = (char *)&cred_handle; arg.gssd_cred_verifier = gssd_cred_verifier; arg.mech_type.GSS_OID_len = (uint_t)(mech_type != GSS_C_NULL_OID ? mech_type->length : 0); arg.mech_type.GSS_OID_val = (char *)(mech_type != GSS_C_NULL_OID ? mech_type->elements : 0); /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_inquire_cred_by_mech_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, * set minor_status to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; /* convert name from external to internal format */ /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_inquire_cred_by_mech_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_inquire_cred_by_mech(minor_status, cred_handle, mech_type, uid) OM_uint32 *minor_status; gss_cred_id_t cred_handle; gss_OID mech_type; uid_t uid; { OM_uint32 gssd_cred_verifier; gssd_cred_id_t gssd_cred_handle; gssd_cred_verifier = KCRED_TO_CREDV(cred_handle); gssd_cred_handle = KCRED_TO_CRED(cred_handle); return (kgss_inquire_cred_by_mech_wrapped(minor_status, gssd_cred_handle, gssd_cred_verifier, mech_type, uid)); } OM_uint32 kgsscred_expname_to_unix_cred(expName, uidOut, gidOut, gids, gidsLen, uid) const gss_buffer_t expName; uid_t *uidOut; gid_t *gidOut; gid_t *gids[]; int *gidsLen; uid_t uid; { gsscred_expname_to_unix_cred_arg args; gsscred_expname_to_unix_cred_res res; /* check input/output parameters */ if (expName == NULL || expName->value == NULL) return (GSS_S_CALL_INACCESSIBLE_READ); if (uidOut == NULL) return (GSS_S_CALL_INACCESSIBLE_WRITE); /* NULL out output parameters */ *uidOut = 0; if (gidsLen) *gidsLen = 0; if (gids) *gids = NULL; /* get the client handle to gssd */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments */ args.uid = uid; args.expname.GSS_BUFFER_T_val = expName->value; args.expname.GSS_BUFFER_T_len = expName->length; /* null out the return buffer and call the remote proc */ memset(&res, 0, sizeof (res)); if (gsscred_expname_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS) { return (GSS_S_FAILURE); } /* copy the results into the result parameters */ if (res.major == GSS_S_COMPLETE) { *uidOut = res.uid; if (gidOut) *gidOut = res.gid; if (gids && gidsLen) { *gids = res.gids.GSSCRED_GIDS_val; *gidsLen = res.gids.GSSCRED_GIDS_len; res.gids.GSSCRED_GIDS_val = NULL; res.gids.GSSCRED_GIDS_len = 0; } } /* free RPC results */ clnt_freeres(clnt, xdr_gsscred_expname_to_unix_cred_res, (caddr_t)&res); return (res.major); } /* kgsscred_expname_to_unix_cred */ OM_uint32 kgsscred_name_to_unix_cred(intName, mechType, uidOut, gidOut, gids, gidsLen, uid) const gss_name_t intName; const gss_OID mechType; uid_t *uidOut; gid_t *gidOut; gid_t *gids[]; int *gidsLen; uid_t uid; { gsscred_name_to_unix_cred_arg args; gsscred_name_to_unix_cred_res res; OM_uint32 major, minor; gss_OID nameOid; gss_buffer_desc flatName = GSS_C_EMPTY_BUFFER; /* check the input/output parameters */ if (intName == NULL || mechType == NULL) return (GSS_S_CALL_INACCESSIBLE_READ); if (uidOut == NULL) return (GSS_S_CALL_INACCESSIBLE_WRITE); /* NULL out the output parameters */ *uidOut = 0; if (gids) *gids = NULL; if (gidsLen) *gidsLen = 0; /* get the client handle to gssd */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* convert the name to flat representation */ if ((major = gss_display_name(&minor, intName, &flatName, &nameOid)) != GSS_S_COMPLETE) { return (major); } /* set the rpc parameters */ args.uid = uid; args.pname.GSS_BUFFER_T_len = flatName.length; args.pname.GSS_BUFFER_T_val = flatName.value; args.name_type.GSS_OID_len = nameOid->length; args.name_type.GSS_OID_val = nameOid->elements; args.mech_type.GSS_OID_len = mechType->length; args.mech_type.GSS_OID_val = mechType->elements; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gsscred_name_to_unix_cred_1(&args, &res, clnt) != RPC_SUCCESS) { gss_release_buffer(&minor, &flatName); return (GSS_S_FAILURE); } gss_release_buffer(&minor, &flatName); /* copy the output parameters on output */ if (res.major == GSS_S_COMPLETE) { *uidOut = res.uid; if (gidOut) *gidOut = res.gid; if (gids && gidsLen) { *gids = res.gids.GSSCRED_GIDS_val; *gidsLen = res.gids.GSSCRED_GIDS_len; res.gids.GSSCRED_GIDS_val = NULL; res.gids.GSSCRED_GIDS_len = 0; } } /* delete RPC allocated memory */ clnt_freeres(clnt, xdr_gsscred_name_to_unix_cred_res, (caddr_t)&res); return (res.major); } /* kgsscred_name_to_unix_cred */ OM_uint32 kgss_get_group_info(puid, gidOut, gids, gidsLen, uid) const uid_t puid; gid_t *gidOut; gid_t *gids[]; int *gidsLen; uid_t uid; { gss_get_group_info_arg args; gss_get_group_info_res res; /* check the output parameters */ if (gidOut == NULL || gids == NULL || gidsLen == NULL) return (GSS_S_CALL_INACCESSIBLE_WRITE); /* get the client GSSD handle */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* set the input parameters */ args.uid = uid; args.puid = puid; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_get_group_info_1(&args, &res, clnt) != RPC_SUCCESS) { return (GSS_S_FAILURE); } /* copy the results */ if (res.major == GSS_S_COMPLETE) { *gidOut = res.gid; *gids = res.gids.GSSCRED_GIDS_val; *gidsLen = res.gids.GSSCRED_GIDS_len; res.gids.GSSCRED_GIDS_val = NULL; res.gids.GSSCRED_GIDS_len = 0; } /* nothing to free */ return (res.major); } /* kgss_get_group_info */ OM_uint32 kgss_export_sec_context_wrapped(minor_status, context_handle, output_token, gssd_context_verifier) OM_uint32 *minor_status; gssd_ctx_id_t *context_handle; gss_buffer_t output_token; OM_uint32 gssd_context_verifier; { CLIENT *clnt; gss_export_sec_context_arg arg; gss_export_sec_context_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.context_handle.GSS_CTX_ID_T_len = (uint_t)sizeof (gssd_ctx_id_t); arg.context_handle.GSS_CTX_ID_T_val = (char *)context_handle; arg.gssd_context_verifier = gssd_context_verifier; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_export_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set minor_status * to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (context_handle != NULL) *context_handle = 0; if (output_token != NULL) output_token->length = 0; return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (res.context_handle.GSS_CTX_ID_T_len == 0) *context_handle = 0; else *context_handle = *((gssd_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val); if (output_token != NULL && res.output_token.GSS_BUFFER_T_val != NULL) { output_token->length = res.output_token.GSS_BUFFER_T_len; output_token->value = (void *) MALLOC(output_token->length); memcpy(output_token->value, res.output_token.GSS_BUFFER_T_val, output_token->length); } /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_export_sec_context_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_export_sec_context(minor_status, context_handle, output_token) OM_uint32 *minor_status; gss_ctx_id_t *context_handle; gss_buffer_t output_token; { OM_uint32 err; struct kgss_ctx *kctx; if (*context_handle == GSS_C_NO_CONTEXT) { return (GSS_S_NO_CONTEXT); } else kctx = KCTX_TO_KGSS_CTX(*context_handle); err = kgss_export_sec_context_wrapped(minor_status, &kctx->gssd_ctx, output_token, kctx->gssd_ctx_verifier); if (GSS_ERROR(err)) return (err); else { KGSS_FREE(kctx); *context_handle = GSS_C_NO_CONTEXT; return (err); } } OM_uint32 kgss_import_sec_context_wrapped(minor_status, input_token, context_handle, gssd_context_verifier) OM_uint32 *minor_status; gss_buffer_t input_token; gss_ctx_id_t *context_handle; OM_uint32 gssd_context_verifier; { CLIENT *clnt; gss_import_sec_context_arg arg; gss_import_sec_context_res res; /* get the client handle to GSSD */ if ((clnt = getgssd_handle()) == NULL) { clnt_pcreateerror(server); return (GSS_S_FAILURE); } /* copy the procedure arguments into the rpc arg parameter */ arg.input_token.GSS_BUFFER_T_len = (uint_t) (input_token != GSS_C_NO_BUFFER ? input_token->length : 0); arg.input_token.GSS_BUFFER_T_val = (char *) (input_token != GSS_C_NO_BUFFER ? input_token->value : 0); arg.gssd_context_verifier = gssd_context_verifier; /* call the remote procedure */ memset(&res, 0, sizeof (res)); if (gss_import_sec_context_1(&arg, &res, clnt) != RPC_SUCCESS) { /* * if the RPC call times out, null out all return arguments, set minor_status * to its maximum value, and return GSS_S_FAILURE */ if (minor_status != NULL) *minor_status = DEFAULT_MINOR_STAT; if (context_handle != NULL) *context_handle = NULL; return (GSS_S_FAILURE); } /* copy the rpc results into the return arguments */ if (minor_status != NULL) *minor_status = res.minor_status; if (res.context_handle.GSS_CTX_ID_T_len == 0) *context_handle = NULL; else *context_handle = *((gss_ctx_id_t *)res.context_handle.GSS_CTX_ID_T_val); /* * free the memory allocated for the results and return with the status * received in the rpc call */ clnt_freeres(clnt, xdr_gss_import_sec_context_res, (caddr_t)&res); return (res.status); } OM_uint32 kgss_import_sec_context(minor_status, input_token, context_handle) OM_uint32 *minor_status; gss_buffer_t input_token; gss_ctx_id_t *context_handle; { struct kgss_ctx *kctx; if (*context_handle == GSS_C_NO_CONTEXT) { kctx = KGSS_ALLOC(); *context_handle = (gss_ctx_id_t)kctx; kctx->gssd_ctx = (OM_uint32) GSS_C_NO_CONTEXT; } else kctx = (struct kgss_ctx *)*context_handle; return (kgss_import_sec_context_wrapped(minor_status, input_token, &kctx->gssd_ctx, KCTX_TO_CTXV(context_handle))); } #ifdef _KERNEL #include static void *gss_clnt = NULL; #ifdef DEBUG typedef struct { char *name; /* just put something here */ } gssd_devstate_t; static void *gssd_state; static int gssd_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) { /* cmn_err(CE_NOTE, "In gssd_attach"); */ switch (cmd) { case DDI_ATTACH: if (ddi_create_minor_node(dip, "gssd", S_IFCHR, 0, "gssd", 0) == DDI_FAILURE) { ddi_remove_minor_node(dip, NULL); return (DDI_FAILURE); } return (DDI_SUCCESS); default: return (DDI_FAILURE); } } static int gssd_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) { dev_t dev; int error; /* cmn_err(CE_NOTE, "In gssd_getinfo"); */ switch (infocmd) { case DDI_INFO_DEVT2INSTANCE: dev = (dev_t)arg; *result = (void *) getminor(dev); error = DDI_SUCCESS; break; case DDI_INFO_DEVT2DEVINFO: /* cmn_err(CE_NOTE, "getinfo wants devinfo"); */ default: error = DDI_FAILURE; break; } return (error); } static int gssd_identify(dev_info_t *dip) { /* cmn_err(CE_NOTE, "in gssd_identify"); */ if (strcmp(ddi_get_name(dip), "gssd") == 0) return (DDI_IDENTIFIED); else return (DDI_NOT_IDENTIFIED); } static int gssd_probe(dev_info_t *dip) { /* cmn_err(CE_NOTE, "In gssd_probe"); */ return (DDI_PROBE_SUCCESS); } static int gssd_open(dev_t *devp, int flag, int otyp, cred_t *credp) { /* cmn_err (CE_NOTE, "In gssd_open"); */ if (otyp != OTYP_CHR) return (EINVAL); gss_clnt = getgssd_handle(); return (0); } static int gssd_close(dev_t dev, int flag, int otyp, cred_t *credp) { /* cmn_err(CE_NOTE, "In gssd_close"); */ killgssd_handle(gss_clnt); return (0); } static int gssd_write(dev_t dev, struct uio *uiop, cred_t *credp) { char buffer[1024]; int len; /* cmn_err(CE_NOTE, "In gssd_write"); */ bzero(buffer, 1024); uiomove(buffer, 1024, UIO_WRITE, uiop); len = strlen(buffer); if (buffer[len-1] == '\n') buffer[--len] = '\0'; cmn_err(CE_NOTE, "Got command: (%d) \"%s\"", len, buffer); do_gssdtest(buffer); return (0); } static struct cb_ops gssd_cb_ops = { gssd_open, /* cb_open */ gssd_close, /* cb_close */ nodev, /* cb_strategy */ nodev, /* cb_print */ nodev, /* cb_dump */ nulldev, /* cb_read */ gssd_write, /* cb_write */ nodev, /* cb_ioctl */ nodev, /* cb_devmap */ nodev, /* cb_mmap */ nodev, /* cb_segmap */ nochpoll, /* cb_chpoll */ ddi_prop_op, /* cb_prop_op */ NULL, /* cb_stream */ (int)(D_NEW|D_MP) /* cb_flag */ }; static struct dev_ops gssd_ops = { DEVO_REV, /* devo_rev */ 0, /* devo_refcnt */ gssd_getinfo, /* devo_getinfo */ gssd_identify, /* devo_identify */ nulldev, /* devo_probe */ gssd_attach, /* devo_attach */ nulldev, /* devo_detach */ nodev, /* devo_reset */ &gssd_cb_ops, /* devo_cb_ops */ (struct bus_ops *)NULL /* devo_bus_ops */ }; extern struct mod_ops mod_driverops; static struct modldrv modlmisc = { &mod_driverops, "GSSD DRV Client Module", &gssd_ops #else /* !DEBUG */ static struct modlmisc modlmisc = { &mod_miscops, "GSSD Client Module" #endif /* DEBUG */ }; static struct modlinkage modlinkage = { MODREV_1, (void *)&modlmisc, NULL }; char _depends_on[] = "strmod/rpcmod misc/tlimod"; _init(void) { int status; if ((status = ddi_soft_state_init(&gssd_state, sizeof (gssd_devstate_t), 1)) != 0) return (status); if ((status = mod_install((struct modlinkage *)&modlinkage)) != 0) ddi_soft_state_fini(&gssd_state); cmn_err(CE_NOTE, "gssd: I'm in the kernel: %d.", status); return (status); } _fini() { int status; killgssd_handle(gss_clnt); cmn_err(CE_NOTE, "gssd: Handle destroyed.. leaving module."); if ((status = mod_remove(&modlinkage)) != 0) return (status); ddi_soft_state_fini(&gssd_state); return (status); } _info(modinfop) struct modinfo *modinfop; { return (mod_info(&modlinkage, modinfop)); } #endif