int gfarmGssImportName(gss_name_t *namePtr, void *nameValue, size_t nameLength, gss_OID nameType, OM_uint32 *majStatPtr, OM_uint32 *minStatPtr) { OM_uint32 majStat = 0; OM_uint32 minStat = 0; int ret = -1; gss_buffer_desc buf; #if GFARM_FAKE_GSS_C_NT_USER_NAME_FOR_GLOBUS if (nameType == GSS_C_NT_USER_NAME) { char *user; gfarmAuthEntry *aePtr; GFARM_MALLOC_ARRAY(user, nameLength + 1); if (user == NULL) { gflog_auth_error(GFARM_MSG_1000611, "gfarmGssImportName(): no memory"); majStat = GSS_S_FAILURE; minStat = GFSL_DEFAULT_MINOR_ERROR; goto Done; } memcpy(user, nameValue, nameLength); user[nameLength] = '\0'; aePtr = gfarmAuthGetLocalUserEntry(user); if (aePtr == NULL) { gflog_auth_error(GFARM_MSG_1000612, "%s: ERROR: cannot convert " "this user name to X.509 Distinguish name", user); free(user); majStat = GSS_S_FAILURE; minStat = GFSL_DEFAULT_MINOR_ERROR; goto Done; } free(user); assert(aePtr->authType == GFARM_AUTH_USER); nameValue = aePtr->distName; nameLength = strlen(aePtr->distName); nameType = GSS_C_NO_OID; /* mechanism specific */ } #endif /* GFARM_FAKE_GSS_C_NT_USER_NAME_FOR_GLOBUS */ buf.length = nameLength; buf.value = nameValue; majStat = gss_import_name(&minStat, &buf, nameType, namePtr); if (majStat == GSS_S_COMPLETE) { ret = 1; /* OK */ } #if GFARM_FAKE_GSS_C_NT_USER_NAME_FOR_GLOBUS Done: #endif /* GFARM_FAKE_GSS_C_NT_USER_NAME_FOR_GLOBUS */ if (majStatPtr != NULL) { *majStatPtr = majStat; } if (minStatPtr != NULL) { *minStatPtr = minStat; } return ret; }
int gfarmGssImportNameOfHostBasedService(gss_name_t *namePtr, char *service, char *hostname, OM_uint32 *majStatPtr, OM_uint32 *minStatPtr) { OM_uint32 majStat; OM_uint32 minStat; int ret = -1; size_t nameLength = strlen(service) + 1 + strlen(hostname); char *nameString; GFARM_MALLOC_ARRAY(nameString, nameLength + 1); if (nameString == NULL) { gflog_auth_error(GFARM_MSG_1000613, "gfarmGssImportNameOfHostBasedService(): " "no memory"); majStat = GSS_S_FAILURE; minStat = GFSL_DEFAULT_MINOR_ERROR; } else { sprintf(nameString, "%s@%s", service, hostname); if (gfarmGssImportName(namePtr, nameString, nameLength, GSS_C_NT_HOSTBASED_SERVICE, &majStat, &minStat) > 0) { ret = 1; } free(nameString); } if (majStatPtr != NULL) { *majStatPtr = majStat; } if (minStatPtr != NULL) { *minStatPtr = minStat; } return ret; }
static void gfarmGssInitiateSecurityContextReceiveToken(int events, int fd, void *closure, const struct timeval *t) { struct gfarmGssInitiateSecurityContextState *state = closure; int tknStat; if ((events & GFARM_EVENT_TIMEOUT) != 0) { assert(events == GFARM_EVENT_TIMEOUT); state->majStat = GSS_S_UNAVAILABLE; /* failure: timeout */ } else { assert(events == GFARM_EVENT_READ); tknStat = gfarmGssReceiveToken(fd, state->itPtr, GFARM_GSS_TIMEOUT_INFINITE); if (tknStat <= 0) { gflog_auth_error(GFARM_MSG_1000624, "gfarmGssInitiateSecurityContextReceiveToken(): " "failed to receive response"); state->majStat= GSS_S_DEFECTIVE_TOKEN|GSS_S_CALL_INACCESSIBLE_READ; state->minStat= GFSL_DEFAULT_MINOR_ERROR; } else if (gssInitiateSecurityContextNext(state)) { return; } } assert(GSS_ERROR(state->majStat) || state->completed); if (state->continuation != NULL) (*state->continuation)(state->closure); }
static void gfarmGssInitiateSecurityContextSendToken(int events, int fd, void *closure, const struct timeval *t) { struct gfarmGssInitiateSecurityContextState *state = closure; int tknStat; OM_uint32 minStat2; tknStat = gfarmGssSendToken(fd, state->otPtr); gss_release_buffer(&minStat2, state->otPtr); if (tknStat <= 0) { gflog_auth_error(GFARM_MSG_1000623, "gfarmGssInitiateSecurityContextSendToken(): " "failed to send response"); state->majStat = GSS_S_DEFECTIVE_TOKEN|GSS_S_CALL_INACCESSIBLE_WRITE; state->minStat = GFSL_DEFAULT_MINOR_ERROR; } if (gssInitiateSecurityContextSwitch(state)) { return; } if (state->continuation != NULL) { (*state->continuation)(state->closure); } }
/* this function returns 1, if an event is added */ static int gssInitiateSecurityContextSwitch( struct gfarmGssInitiateSecurityContextState *state) { int rv; struct timeval timeout; if (GSS_ERROR(state->majStat)) { return 0; } if (state->majStat & GSS_S_CONTINUE_NEEDED) { timeout.tv_sec = GFARM_GSS_AUTH_TIMEOUT; timeout.tv_usec = 0; rv = gfarm_eventqueue_add_event(state->q, state->readable, &timeout); if (rv == 0) { /* go to gfarmGssInitiateSecurityContextReceiveToken() */ return 1; } gflog_auth_error(GFARM_MSG_1000621, "gfarm:gssInitiateSecurityContextSwitch(): %s", strerror(rv)); state->majStat = GSS_S_FAILURE; state->minStat = GFSL_DEFAULT_MINOR_ERROR; } else { state->completed = 1; } return 0; }
char * gfarmGssNewDisplayName(const gss_name_t inputName, OM_uint32 *majStatPtr, OM_uint32 *minStatPtr, gss_OID *outputNameTypePtr) { OM_uint32 majStat; OM_uint32 minStat, minStat2; char *ret = NULL; gss_buffer_desc buf; gss_OID outputNameType; if (inputName == GSS_C_NO_NAME) { gflog_auth_error(GFARM_MSG_1000614, "gfarmGssNewDisplayName(): GSS_C_NO_NAME is passed"); majStat = GSS_S_FAILURE; minStat = GFSL_DEFAULT_MINOR_ERROR; } else if ((majStat = gss_display_name(&minStat, inputName, &buf, &outputNameType)) == GSS_S_COMPLETE) { GFARM_MALLOC_ARRAY(ret, buf.length + 1); if (ret == NULL) { gflog_auth_error(GFARM_MSG_1000615, "gfarmGssNewDisplayName(): no memory"); majStat = GSS_S_FAILURE; minStat = GFSL_DEFAULT_MINOR_ERROR; } else { ret[buf.length] = '\0'; memcpy(ret, buf.value, buf.length); gss_release_buffer(&minStat2, &buf); if (outputNameTypePtr != NULL) { *outputNameTypePtr = outputNameType; } } } if (majStatPtr != NULL) { *majStatPtr = majStat; } if (minStatPtr != NULL) { *minStatPtr = minStat; } return ret; }
/* this function returns 1, if an event is added */ static int gssInitiateSecurityContextNext( struct gfarmGssInitiateSecurityContextState *state) { OM_uint32 minStat2; int rv; static const char diag[] = "gssInitiateSecurityContextNext()"; gfarm_mutex_lock(&gss_mutex, diag, gssDiag); state->majStat = gss_init_sec_context(&state->minStat, state->cred, &state->sc, state->acceptorName, GSS_C_NO_OID, state->reqFlag, 0, GSS_C_NO_CHANNEL_BINDINGS, state->itPtr, state->actualMechType, state->otPtr, &state->retFlag, &state->timeRet); gfarm_mutex_unlock(&gss_mutex, diag, gssDiag); if (state->itPtr->length > 0) gss_release_buffer(&minStat2, state->itPtr); if (state->otPtr->length > 0) { rv = gfarm_eventqueue_add_event(state->q, state->writable, NULL); if (rv == 0) { /* go to gfarmGssInitiateSecurityContextSendToken() */ return 1; } gflog_auth_error(GFARM_MSG_1000622, "gfarm:gssInitiateSecurityContextNext(): %s", strerror(rv)); state->majStat = GSS_S_FAILURE; state->minStat = GFSL_DEFAULT_MINOR_ERROR; } return gssInitiateSecurityContextSwitch(state); }
char * gfarm_gsi_client_cred_name(void) { gss_cred_id_t cred; gss_name_t name; OM_uint32 e_major, e_minor; static int initialized = 0; static char *dn; if (initialized) return (dn); if (gfarmSecSessionGetInitiatorInitialCredential(&cred) < 0) { dn = NULL; gflog_auth_error("gfarm_gsi_client_cred_name(): " "not initialized as an initiator"); } else if (gfarmGssNewCredentialName(&name, cred, &e_major, &e_minor) < 0) { dn = NULL; if (gflog_auth_get_verbose()) { gflog_error("cannot convert initiator credential " "to name"); gfarmGssPrintMajorStatus(e_major); gfarmGssPrintMinorStatus(e_minor); } } else { dn = gfarmGssNewDisplayName(name, &e_major, &e_minor, NULL); if (dn == NULL && gflog_auth_get_verbose()) { gflog_error("cannot convert initiator credential " "to string"); gfarmGssPrintMajorStatus(e_major); gfarmGssPrintMinorStatus(e_minor); } gfarmGssDeleteName(&name, NULL, NULL); } initialized = 1; return (dn); }
int gfarmGssInitiateSecurityContext(int fd, const gss_name_t acceptorName, gss_cred_id_t cred, OM_uint32 reqFlag, gss_ctx_id_t *scPtr, OM_uint32 *majStatPtr, OM_uint32 *minStatPtr, gss_name_t *remoteNamePtr) { OM_uint32 majStat; OM_uint32 minStat, minStat2; OM_uint32 retFlag = 0; gss_buffer_desc inputToken = GSS_C_EMPTY_BUFFER; gss_buffer_t itPtr = &inputToken; gss_buffer_desc outputToken = GSS_C_EMPTY_BUFFER; gss_buffer_t otPtr = &outputToken; gss_OID *actualMechType = NULL; OM_uint32 timeRet; int tknStat; static const char diag[] = "gfarmGssInitiateSecurityContext()"; *scPtr = GSS_C_NO_CONTEXT; /* * Implementation specification: * In gfarm, an initiator must reveal own identity to an acceptor. */ if ((reqFlag & GSS_C_ANON_FLAG) == GSS_C_ANON_FLAG) { /* It is a bit safer to deny the request than to silently ignore it */ gflog_auth_error(GFARM_MSG_1000618, "gfarmGssInitiateSecurityContext(): " "GSS_C_ANON_FLAG is not allowed"); majStat = GSS_S_UNAVAILABLE; minStat = GFSL_DEFAULT_MINOR_ERROR; goto Done; } while (1) { gfarm_mutex_lock(&gss_mutex, diag, gssDiag); majStat = gss_init_sec_context(&minStat, cred, scPtr, acceptorName, GSS_C_NO_OID, reqFlag, 0, GSS_C_NO_CHANNEL_BINDINGS, itPtr, actualMechType, otPtr, &retFlag, &timeRet); gfarm_mutex_unlock(&gss_mutex, diag, gssDiag); if (itPtr->length > 0) gss_release_buffer(&minStat2, itPtr); if (otPtr->length > 0) { tknStat = gfarmGssSendToken(fd, otPtr); gss_release_buffer(&minStat2, otPtr); if (tknStat <= 0) { gflog_auth_error(GFARM_MSG_1000619, "gfarmGssInitiateSecurityContext(): " "failed to send response"); majStat = GSS_S_DEFECTIVE_TOKEN|GSS_S_CALL_INACCESSIBLE_WRITE; minStat = GFSL_DEFAULT_MINOR_ERROR; } } if (GSS_ERROR(majStat)) { break; } if (majStat & GSS_S_CONTINUE_NEEDED) { tknStat = gfarmGssReceiveToken(fd, itPtr, GFARM_GSS_TIMEOUT_INFINITE); if (tknStat <= 0) { gflog_auth_error(GFARM_MSG_1000620, "gfarmGssInitiateSecurityContext(): " "failed to receive response"); majStat = GSS_S_DEFECTIVE_TOKEN|GSS_S_CALL_INACCESSIBLE_READ; minStat = GFSL_DEFAULT_MINOR_ERROR; break; } } else { break; } } if (itPtr->length > 0) gss_release_buffer(&minStat2, itPtr); if (majStat == GSS_S_COMPLETE && remoteNamePtr != NULL) { majStat = gss_inquire_context(&minStat, *scPtr, NULL, remoteNamePtr, NULL, NULL, NULL, NULL, NULL); } Done: if (majStatPtr != NULL) *majStatPtr = majStat; if (minStatPtr != NULL) *minStatPtr = minStat; if (majStat != GSS_S_COMPLETE && *scPtr != GSS_C_NO_CONTEXT) gss_delete_sec_context(&minStat2, scPtr, GSS_C_NO_BUFFER); return majStat == GSS_S_COMPLETE ? 1 : -1; }
struct gfarmGssInitiateSecurityContextState * gfarmGssInitiateSecurityContextRequest(struct gfarm_eventqueue *q, int fd, const gss_name_t acceptorName, gss_cred_id_t cred, OM_uint32 reqFlag, void (*continuation) (void *), void *closure, OM_uint32 *majStatPtr, OM_uint32 *minStatPtr) { OM_uint32 majStat; OM_uint32 minStat; struct gfarmGssInitiateSecurityContextState *state; /* * Implementation specification: * In gfarm, an initiator must reveal own identity to an acceptor. */ if ((reqFlag & GSS_C_ANON_FLAG) == GSS_C_ANON_FLAG) { /* It is a bit safer to deny the request than to silently ignore it */ gflog_auth_error(GFARM_MSG_1000625, "gfarmGssInitiateSecurityContextRequest(): " "GSS_C_ANON_FLAG is not allowed"); majStat = GSS_S_UNAVAILABLE; minStat = GFSL_DEFAULT_MINOR_ERROR; goto ReturnStat; } GFARM_MALLOC(state); if (state == NULL) { gflog_auth_error(GFARM_MSG_1000626, "gfarmGssInitiateSecurityContextRequest(): " "no memory"); majStat = GSS_S_FAILURE; minStat = GFSL_DEFAULT_MINOR_ERROR; goto ReturnStat; } state->completed = 0; state->majStat = GSS_S_COMPLETE; state->minStat = GFSL_DEFAULT_MINOR_ERROR; state->writable = gfarm_fd_event_alloc(GFARM_EVENT_WRITE, fd, gfarmGssInitiateSecurityContextSendToken, state); if (state->writable == NULL) { gflog_auth_error(GFARM_MSG_1000627, "gfarmGssInitiateSecurityContextRequest(): " "no memory"); state->majStat = GSS_S_FAILURE; goto FreeState; } /* * We cannot use two independent events (i.e. a fd_event with * GFARM_EVENT_READ flag and a timer_event) here, because * it's possible that both event handlers are called at once. */ state->readable = gfarm_fd_event_alloc(GFARM_EVENT_READ|GFARM_EVENT_TIMEOUT, fd, gfarmGssInitiateSecurityContextReceiveToken, state); if (state->readable == NULL) { gflog_auth_error(GFARM_MSG_1000628, "gfarmGssInitiateSecurityContextRequest(): " "no memory"); state->majStat = GSS_S_FAILURE; goto FreeWritable; } state->q = q; state->fd = fd; state->acceptorName = acceptorName; state->cred = cred; state->reqFlag = reqFlag; state->continuation = continuation; state->closure = closure; state->retFlag = 0; /* GSS_C_EMPTY_BUFFER */ state->inputToken.length = 0; state->inputToken.value = NULL; state->itPtr = &state->inputToken; /* GSS_C_EMPTY_BUFFER */ state->outputToken.length = 0; state->outputToken.value = NULL; state->otPtr = &state->outputToken; state->actualMechType = NULL; state->sc = GSS_C_NO_CONTEXT; gssInitiateSecurityContextNext(state); assert(!state->completed); if (!GSS_ERROR(state->majStat)) { if (majStatPtr != NULL) { *majStatPtr = GSS_S_COMPLETE; } if (minStatPtr != NULL) { *minStatPtr = GFSL_DEFAULT_MINOR_ERROR; } return (state); } gfarm_event_free(state->readable); FreeWritable: gfarm_event_free(state->writable); FreeState: majStat = state->majStat; minStat = state->minStat; free(state); ReturnStat: if (majStatPtr != NULL) *majStatPtr = majStat; if (minStatPtr != NULL) *minStatPtr = minStat; if (GSS_ERROR(majStat)) { gflog_debug(GFARM_MSG_1000801, "failed to request initiate security context (%u)(%u)", majStat, minStat); } return (NULL); }