static void nfs_Init(const nfs_start_info_t *p_start_info) { cache_inode_status_t cache_status; state_status_t state_status; int rc = 0; #ifdef _HAVE_GSSAPI gss_buffer_desc gss_service_buf; OM_uint32 maj_stat, min_stat; char GssError[MAXNAMLEN + 1]; #endif #ifdef USE_DBUS /* DBUS init */ gsh_dbus_pkginit(); #ifdef USE_DBUS_STATS dbus_export_init(); dbus_client_init(); #endif #endif /* Cache Inode Initialisation */ cache_status = cache_inode_init(); if (cache_status != CACHE_INODE_SUCCESS) { LogFatal(COMPONENT_INIT, "Cache Inode Layer could not be initialized, status=%s", cache_inode_err_str(cache_status)); } state_status = state_lock_init(nfs_param.cache_param.cookie_param); if (state_status != STATE_SUCCESS) { LogFatal(COMPONENT_INIT, "State Lock Layer could not be initialized, status=%s", state_err_str(state_status)); } LogInfo(COMPONENT_INIT, "Cache Inode library successfully initialized"); /* Cache Inode LRU (call this here, rather than as part of cache_inode_init() so the GC policy has been set */ rc = cache_inode_lru_pkginit(); if (rc != 0) { LogFatal(COMPONENT_INIT, "Unable to initialize LRU subsystem: %d.", rc); } /* finish the job with exports by caching the root entries */ exports_pkginit(); nfs41_session_pool = pool_init("NFSv4.1 session pool", sizeof(nfs41_session_t), pool_basic_substrate, NULL, NULL, NULL); request_pool = pool_init("Request pool", sizeof(request_data_t), pool_basic_substrate, NULL, NULL /* FASTER constructor_request_data_t */ , NULL); if (!request_pool) { LogCrit(COMPONENT_INIT, "Error while allocating request pool"); LogError(COMPONENT_INIT, ERR_SYS, ERR_MALLOC, errno); Fatal(); } request_data_pool = pool_init("Request Data Pool", sizeof(nfs_request_data_t), pool_basic_substrate, NULL, NULL /* FASTER constructor_nfs_request_data_t */ , NULL); if (!request_data_pool) { LogCrit(COMPONENT_INIT, "Error while allocating request data pool"); LogError(COMPONENT_INIT, ERR_SYS, ERR_MALLOC, errno); Fatal(); } dupreq_pool = pool_init("Duplicate Request Pool", sizeof(dupreq_entry_t), pool_basic_substrate, NULL, NULL, NULL); if (!(dupreq_pool)) { LogCrit(COMPONENT_INIT, "Error while allocating duplicate request pool"); LogError(COMPONENT_INIT, ERR_SYS, ERR_MALLOC, errno); Fatal(); } #ifdef _USE_ASYNC_CACHE_INODE /* Start the TAD and synclets for writeback cache inode */ cache_inode_async_init(nfs_param.cache_layers_param. cache_inode_client_param); #endif /* If rpcsec_gss is used, set the path to the keytab */ #ifdef _HAVE_GSSAPI #ifdef HAVE_KRB5 if (nfs_param.krb5_param.active_krb5) { OM_uint32 gss_status = GSS_S_COMPLETE; if (nfs_param.krb5_param.keytab[0] != '\0') gss_status = krb5_gss_register_acceptor_identity(nfs_param. krb5_param. keytab); if (gss_status != GSS_S_COMPLETE) { log_sperror_gss(GssError, gss_status, 0); LogFatal(COMPONENT_INIT, "Error setting krb5 keytab to value %s is %s", nfs_param.krb5_param.keytab, GssError); } LogInfo(COMPONENT_INIT, "krb5 keytab path successfully set to %s", nfs_param.krb5_param.keytab); #endif /* HAVE_KRB5 */ /* Set up principal to be use for GSSAPPI within GSSRPC/KRB5 */ gss_service_buf.value = nfs_param.krb5_param.svc.principal; gss_service_buf.length = strlen(nfs_param.krb5_param.svc.principal) + 1; /* The '+1' is not to be forgotten, for the '\0' at the end */ maj_stat = gss_import_name(&min_stat, &gss_service_buf, (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &nfs_param.krb5_param.svc.gss_name); if (maj_stat != GSS_S_COMPLETE) { log_sperror_gss(GssError, maj_stat, min_stat); LogFatal(COMPONENT_INIT, "Error importing gss principal %s is %s", nfs_param.krb5_param.svc.principal, GssError); } if (nfs_param.krb5_param.svc.gss_name == GSS_C_NO_NAME) LogInfo(COMPONENT_INIT, "Regression: svc.gss_name == GSS_C_NO_NAME"); LogInfo(COMPONENT_INIT, "gss principal \"%s\" successfully set", nfs_param.krb5_param.svc.principal); /* Set the principal to GSSRPC */ if (!svcauth_gss_set_svc_name (nfs_param.krb5_param.svc.gss_name)) { LogFatal(COMPONENT_INIT, "Impossible to set gss principal to GSSRPC"); } /* Don't release name until shutdown, it will be used by the * backchannel. */ #ifdef HAVE_KRB5 } /* if( nfs_param.krb5_param.active_krb5 ) */ #endif /* HAVE_KRB5 */ #endif /* _HAVE_GSSAPI */ /* RPC Initialisation - exits on failure */ nfs_Init_svc(); LogInfo(COMPONENT_INIT, "RPC ressources successfully initialized"); /* Admin initialisation */ nfs_Init_admin_thread(); LogEvent(COMPONENT_INIT, "Initializing ID Mapper."); if (!idmapper_init()) LogFatal(COMPONENT_INIT, "Failed initializing ID Mapper."); else LogEvent(COMPONENT_INIT, "ID Mapper successfully initialized."); /* Init the NFSv4 Clientid cache */ LogDebug(COMPONENT_INIT, "Now building NFSv4 clientid cache"); if (nfs_Init_client_id(&nfs_param.client_id_param) != CLIENT_ID_SUCCESS) { LogFatal(COMPONENT_INIT, "Error while initializing NFSv4 clientid cache"); } LogInfo(COMPONENT_INIT, "NFSv4 clientid cache successfully initialized"); /* Init duplicate request cache */ dupreq2_pkginit(); LogInfo(COMPONENT_INIT, "duplicate request hash table cache successfully initialized"); /* Init the IP/name cache */ LogDebug(COMPONENT_INIT, "Now building IP/name cache"); if (nfs_Init_ip_name(nfs_param.ip_name_param) != IP_NAME_SUCCESS) { LogFatal(COMPONENT_INIT, "Error while initializing IP/name cache"); } LogInfo(COMPONENT_INIT, "IP/name cache successfully initialized"); /* Init The NFSv4 State id cache */ LogDebug(COMPONENT_INIT, "Now building NFSv4 State Id cache"); if (nfs4_Init_state_id(&nfs_param.state_id_param) != 0) { LogFatal(COMPONENT_INIT, "Error while initializing NFSv4 State Id cache"); } LogInfo(COMPONENT_INIT, "NFSv4 State Id cache successfully initialized"); /* Init The NFSv4 Open Owner cache */ LogDebug(COMPONENT_INIT, "Now building NFSv4 Owner cache"); if (Init_nfs4_owner(&nfs_param.nfs4_owner_param) != 0) { LogFatal(COMPONENT_INIT, "Error while initializing NFSv4 Owner cache"); } LogInfo(COMPONENT_INIT, "NFSv4 Open Owner cache successfully initialized"); if (nfs_param.core_param.enable_NLM) { /* Init The NLM Owner cache */ LogDebug(COMPONENT_INIT, "Now building NLM Owner cache"); if (Init_nlm_hash() != 0) { LogFatal(COMPONENT_INIT, "Error while initializing NLM Owner cache"); } LogInfo(COMPONENT_INIT, "NLM Owner cache successfully initialized"); nlm_init(); } #ifdef _USE_9P /* Init the 9P lock owner cache */ LogDebug(COMPONENT_INIT, "Now building 9P Owner cache"); if (Init_9p_hash() != 0) { LogFatal(COMPONENT_INIT, "Error while initializing 9P Owner cache"); } LogInfo(COMPONENT_INIT, "9P Owner cache successfully initialized"); #endif LogDebug(COMPONENT_INIT, "Now building NFSv4 Session Id cache"); if (nfs41_Init_session_id(&nfs_param.session_id_param) != 0) { LogFatal(COMPONENT_INIT, "Error while initializing NFSv4 Session Id cache"); } LogInfo(COMPONENT_INIT, "NFSv4 Session Id cache successfully initialized"); LogDebug(COMPONENT_INIT, "Now building NFSv4 ACL cache"); if (nfs4_acls_init() != 0) { LogCrit(COMPONENT_INIT, "Error while initializing NFSv4 ACLs"); exit(1); } LogInfo(COMPONENT_INIT, "NFSv4 ACL cache successfully initialized"); #ifdef _USE_9P LogDebug(COMPONENT_INIT, "Now building 9P resources"); if (_9p_init(&nfs_param._9p_param)) { LogCrit(COMPONENT_INIT, "Error while initializing 9P Resources"); exit(1); } LogInfo(COMPONENT_INIT, "9P resources successfully initialized"); #endif /* _USE_9P */ /* Creates the pseudo fs */ LogDebug(COMPONENT_INIT, "Now building pseudo fs"); rc = nfs4_ExportToPseudoFS(); if (rc != 0) LogFatal(COMPONENT_INIT, "Error %d while initializing NFSv4 pseudo file system", rc); LogInfo(COMPONENT_INIT, "NFSv4 pseudo file system successfully initialized"); /* Save Ganesha thread credentials with Frank's routine for later use */ fsal_save_ganesha_credentials(); /* Create stable storage directory, this needs to be done before * starting the recovery thread. */ nfs4_create_recov_dir(); /* initialize grace and read in the client IDs */ nfs4_init_grace(); nfs4_load_recov_clids(NULL); /* Start grace period */ nfs4_start_grace(NULL); /* callback dispatch */ nfs_rpc_cb_pkginit(); #ifdef _USE_CB_SIMULATOR nfs_rpc_cbsim_pkginit(); #endif /* _USE_CB_SIMULATOR */ } /* nfs_Init */
int nfs_rpc_req2client_cred(struct svc_req *reqp, nfs_client_cred_t * pcred) { /* Structure for managing basic AUTH_UNIX authentication */ struct authunix_parms *aup = NULL; /* Stuff needed for managing RPCSEC_GSS */ #ifdef _HAVE_GSSAPI OM_uint32 maj_stat = 0; OM_uint32 min_stat = 0; struct svc_rpc_gss_data *gd = NULL; gss_buffer_desc oidbuff; #endif if(reqp == NULL || pcred == NULL) return -1; pcred->flavor = reqp->rq_cred.oa_flavor; pcred->length = reqp->rq_cred.oa_length; switch (reqp->rq_cred.oa_flavor) { case AUTH_NONE: /* Do nothing... because there seems like nothing is to be done... */ break; case AUTH_UNIX: aup = (struct authunix_parms *)(reqp->rq_clntcred); pcred->auth_union.auth_unix.aup_uid = aup->aup_uid; pcred->auth_union.auth_unix.aup_gid = aup->aup_gid; pcred->auth_union.auth_unix.aup_time = aup->aup_time; break; #ifdef _HAVE_GSSAPI case RPCSEC_GSS: /* Extract the information from the RPCSEC_GSS opaque structure */ gd = SVCAUTH_PRIVATE(reqp->rq_xprt->xp_auth); pcred->auth_union.auth_gss.svc = (unsigned int)(gd->sec.svc); pcred->auth_union.auth_gss.qop = (unsigned int)(gd->sec.qop); pcred->auth_union.auth_gss.gss_context_id = gd->ctx; strncpy(pcred->auth_union.auth_gss.cname, gd->cname.value, NFS_CLIENT_NAME_LEN); if((maj_stat = gss_oid_to_str(&min_stat, gd->sec.mech, &oidbuff)) != GSS_S_COMPLETE) { char errbuff[1024]; log_sperror_gss(errbuff, maj_stat, min_stat); LogCrit(COMPONENT_DISPATCH, "GSSAPI ERROR: %u|%u = %s", maj_stat, min_stat, errbuff); return -1; } strncpy(pcred->auth_union.auth_gss.stroid, oidbuff.value, NFS_CLIENT_NAME_LEN); /* Je fais le menage derriere moi */ (void)gss_release_buffer(&min_stat, &oidbuff); break; #endif default: /* Unsupported authentication flavour */ return -1; break; } return 1; } /* nfs_rpc_req2client_cred */
static bool_t Svcauth_gss_validate(struct svc_req *rqst, struct svc_rpc_gss_data *gd, struct rpc_msg *msg) { struct opaque_auth *oa; gss_buffer_desc rpcbuf, checksum; OM_uint32 maj_stat, min_stat, qop_state; u_char rpchdr[128]; int32_t *buf; char GssError[256]; memset(rpchdr, 0, sizeof(rpchdr)); /* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */ oa = &msg->rm_call.cb_cred; LogFullDebug(COMPONENT_RPCSEC_GSS, "Call to Svcauth_gss_validate --> xid=%u dir=%u rpcvers=%u prog=%u vers=%u proc=%u flavor=%u len=%u base=%p ckeck.len=%u check.val=%p", msg->rm_xid, msg->rm_direction, msg->rm_call.cb_rpcvers, msg->rm_call.cb_prog, msg->rm_call.cb_vers, msg->rm_call.cb_proc, oa->oa_flavor, oa->oa_length, oa->oa_base, msg->rm_call.cb_verf.oa_length, msg->rm_call.cb_verf.oa_base); if(oa->oa_length > MAX_AUTH_BYTES) { LogCrit(COMPONENT_RPCSEC_GSS, "Svcauth_gss_validate oa->oa_length (%u) > MAX_AUTH_BYTES (%u)", oa->oa_length, MAX_AUTH_BYTES); return (FALSE); } /* 8 XDR units from the IXDR macro calls. */ if(sizeof(rpchdr) < (8 * BYTES_PER_XDR_UNIT + RNDUP(oa->oa_length))) { LogCrit(COMPONENT_RPCSEC_GSS, "Svcauth_gss_validate sizeof(rpchdr) (%d) < (8 * BYTES_PER_XDR_UNIT (%d) + RNDUP(oa->oa_length (%u))) (%d)", (int) sizeof(rpchdr), (int) (8 * BYTES_PER_XDR_UNIT), oa->oa_length, (int) (8 * BYTES_PER_XDR_UNIT + RNDUP(oa->oa_length))); return (FALSE); } buf = (int32_t *) (void *)rpchdr; IXDR_PUT_LONG(buf, msg->rm_xid); IXDR_PUT_ENUM(buf, msg->rm_direction); IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers); IXDR_PUT_LONG(buf, msg->rm_call.cb_prog); IXDR_PUT_LONG(buf, msg->rm_call.cb_vers); IXDR_PUT_LONG(buf, msg->rm_call.cb_proc); IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if(oa->oa_length) { memcpy((caddr_t) buf, oa->oa_base, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof(int32_t); } rpcbuf.value = rpchdr; rpcbuf.length = (u_char *) buf - rpchdr; checksum.value = msg->rm_call.cb_verf.oa_base; checksum.length = msg->rm_call.cb_verf.oa_length; if(isFullDebug(COMPONENT_RPCSEC_GSS)) { char ctx_str[64]; sprint_ctx(ctx_str, (unsigned char *)gd->ctx, sizeof(gss_union_ctx_id_desc)); LogFullDebug(COMPONENT_RPCSEC_GSS, "Svcauth_gss_validate context %s rpcbuf=%p:%u checksum=%p:$%u)", ctx_str, rpcbuf.value, (unsigned int) rpcbuf.length, checksum.value, (unsigned int) checksum.length); } maj_stat = gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum, &qop_state); if(maj_stat != GSS_S_COMPLETE) { log_sperror_gss(GssError, maj_stat, min_stat); LogCrit(COMPONENT_RPCSEC_GSS, "Error in gss_verify_mic: %s", GssError); return (FALSE); } return (TRUE); }