void gpm_free_xdrs(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res) { xdr_free(gpm_xdr_set[proc].arg_fn, (char *)arg); xdr_free(gpm_xdr_set[proc].res_fn, (char *)res); }
/* * @server: the unlocked server object * @client: the unlocked client object * @msg: the complete incoming method call, with header already decoded * * This method is used to dispatch a message representing an * incoming method call from a client. It decodes the payload * to obtain method call arguments, invokves the method and * then sends a reply packet with the return values * * Returns 0 if the reply was sent, or -1 upon fatal error */ static int virNetServerProgramDispatchCall(virNetServerProgramPtr prog, virNetServerPtr server, virNetServerClientPtr client, virNetMessagePtr msg) { char *arg = NULL; char *ret = NULL; int rv = -1; virNetServerProgramProcPtr dispatcher; virNetMessageError rerr; size_t i; virIdentityPtr identity = NULL; memset(&rerr, 0, sizeof(rerr)); if (msg->header.status != VIR_NET_OK) { virReportError(VIR_ERR_RPC, _("Unexpected message status %u"), msg->header.status); goto error; } dispatcher = virNetServerProgramGetProc(prog, msg->header.proc); if (!dispatcher) { virReportError(VIR_ERR_RPC, _("unknown procedure: %d"), msg->header.proc); goto error; } /* If client is marked as needing auth, don't allow any RPC ops * which are except for authentication ones */ if (virNetServerClientNeedAuth(client) && dispatcher->needAuth) { /* Explicitly *NOT* calling remoteDispatchAuthError() because we want back-compatibility with libvirt clients which don't support the VIR_ERR_AUTH_FAILED error code */ virReportError(VIR_ERR_RPC, "%s", _("authentication required")); goto error; } if (VIR_ALLOC_N(arg, dispatcher->arg_len) < 0) goto error; if (VIR_ALLOC_N(ret, dispatcher->ret_len) < 0) goto error; if (virNetMessageDecodePayload(msg, dispatcher->arg_filter, arg) < 0) goto error; if (!(identity = virNetServerClientGetIdentity(client))) goto error; if (virIdentitySetCurrent(identity) < 0) goto error; /* * When the RPC handler is called: * * - Server object is unlocked * - Client object is unlocked * * Without locking, it is safe to use: * * 'args and 'ret' */ rv = (dispatcher->func)(server, client, msg, &rerr, arg, ret); if (virIdentitySetCurrent(NULL) < 0) goto error; /* * If rv == 1, this indicates the dispatch func has * populated 'msg' with a list of FDs to return to * the caller. * * Otherwise we must clear out the FDs we got from * the client originally. * */ if (rv != 1) { for (i = 0; i < msg->nfds; i++) VIR_FORCE_CLOSE(msg->fds[i]); VIR_FREE(msg->fds); msg->nfds = 0; } xdr_free(dispatcher->arg_filter, arg); if (rv < 0) goto error; /* Return header. We're re-using same message object, so * only need to tweak type/status fields */ /*msg->header.prog = msg->header.prog;*/ /*msg->header.vers = msg->header.vers;*/ /*msg->header.proc = msg->header.proc;*/ msg->header.type = msg->nfds ? VIR_NET_REPLY_WITH_FDS : VIR_NET_REPLY; /*msg->header.serial = msg->header.serial;*/ msg->header.status = VIR_NET_OK; if (virNetMessageEncodeHeader(msg) < 0) { xdr_free(dispatcher->ret_filter, ret); goto error; } if (msg->nfds && virNetMessageEncodeNumFDs(msg) < 0) { xdr_free(dispatcher->ret_filter, ret); goto error; } if (virNetMessageEncodePayload(msg, dispatcher->ret_filter, ret) < 0) { xdr_free(dispatcher->ret_filter, ret); goto error; } xdr_free(dispatcher->ret_filter, ret); VIR_FREE(arg); VIR_FREE(ret); virObjectUnref(identity); /* Put reply on end of tx queue to send out */ return virNetServerClientSendMessage(client, msg); error: /* Bad stuff (de-)serializing message, but we have an * RPC error message we can send back to the client */ rv = virNetServerProgramSendReplyError(prog, client, msg, &rerr, &msg->header); VIR_FREE(arg); VIR_FREE(ret); virObjectUnref(identity); return rv; }
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; struct acquire_cred_res res; struct acquire_cred_args args; enum clnt_stat stat; gss_cred_id_t cred; int i; CLIENT *cl; *minor_status = 0; cl = kgss_gssd_client(); if (cl == NULL) return (GSS_S_FAILURE); args.uid = curthread->td_ucred->cr_uid; if (desired_name) args.desired_name = desired_name->handle; else args.desired_name = 0; args.time_req = time_req; args.desired_mechs = desired_mechs; args.cred_usage = cred_usage; bzero(&res, sizeof(res)); stat = gssd_acquire_cred_1(&args, &res, cl); CLNT_RELEASE(cl); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); } if (res.major_status != GSS_S_COMPLETE) { *minor_status = res.minor_status; return (res.major_status); } cred = malloc(sizeof(struct _gss_cred_id_t), M_GSSAPI, M_WAITOK); cred->handle = res.output_cred; *output_cred_handle = cred; if (actual_mechs) { major_status = gss_create_empty_oid_set(minor_status, actual_mechs); if (major_status) return (major_status); for (i = 0; i < res.actual_mechs->count; i++) { major_status = gss_add_oid_set_member(minor_status, &res.actual_mechs->elements[i], actual_mechs); if (major_status) return (major_status); } } if (time_rec) *time_rec = res.time_rec; xdr_free((xdrproc_t) xdr_acquire_cred_res, &res); return (GSS_S_COMPLETE); }
static enum nss_status internal_nisplus_getpwent_r (struct passwd *pw, char *buffer, size_t buflen, int *errnop) { int parse_res = -1; enum nss_status retval = NSS_STATUS_SUCCESS; /* Get the next entry until we found a correct one. */ do { nis_error status; nis_result result; memset (&result, '\0', sizeof (result)); if (cursor.n_bytes == NULL) { if (ibreq == NULL) { retval = internal_nisplus_setpwent (errnop); if (retval != NSS_STATUS_SUCCESS) return retval; } status = __do_niscall3 (&bptr, NIS_IBFIRST, (xdrproc_t) _xdr_ib_request, (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result, (caddr_t) &result, 0, NULL); } else { ibreq->ibr_cookie.n_bytes = cursor.n_bytes; ibreq->ibr_cookie.n_len = cursor.n_len; status = __do_niscall3 (&bptr, NIS_IBNEXT, (xdrproc_t) _xdr_ib_request, (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result, (caddr_t) &result, 0, NULL); ibreq->ibr_cookie.n_bytes = NULL; ibreq->ibr_cookie.n_len = 0; } if (status != NIS_SUCCESS) return niserr2nss (status); if (NIS_RES_STATUS (&result) == NIS_NOTFOUND) { /* No more entries on this server. This means we have to go to the next server on the path. */ status = __follow_path (&tablepath, &tableptr, ibreq, &bptr); if (status != NIS_SUCCESS) return niserr2nss (status); directory_obj *newdir = NULL; dir_binding newbptr; status = __prepare_niscall (ibreq->ibr_name, &newdir, &newbptr, 0); if (status != NIS_SUCCESS) return niserr2nss (status); nis_free_directory (dir); dir = newdir; __nisbind_destroy (&bptr); bptr = newbptr; xdr_free ((xdrproc_t) xdr_netobj, (char *) &result.cookie); result.cookie.n_bytes = NULL; result.cookie.n_len = 0; parse_res = 0; goto next; } else if (NIS_RES_STATUS (&result) != NIS_SUCCESS) return niserr2nss (NIS_RES_STATUS (&result)); parse_res = _nss_nisplus_parse_pwent (&result, pw, buffer, buflen, errnop); if (parse_res == -1) { *errnop = ERANGE; retval = NSS_STATUS_TRYAGAIN; goto freeres; } next: /* Free the old cursor. */ xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor); /* Remember the new one. */ cursor.n_bytes = result.cookie.n_bytes; cursor.n_len = result.cookie.n_len; /* Free the result structure. NB: we do not remove the cookie. */ result.cookie.n_bytes = NULL; result.cookie.n_len = 0; freeres: xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &result); memset (&result, '\0', sizeof (result)); } while (!parse_res); return retval; }
/*ARGSUSED*/ bool_t metad_2_freeresult(SVCXPRT *unused, xdrproc_t xdr_result, caddr_t result) { xdr_free(xdr_result, result); return (TRUE); }
//Liberar memoria de los resultados. int ssdd_text_1_freeresult(SVCXPRT *svcx_prt, xdrproc_t xdr_proc, caddr_t c_addr) { xdr_free(xdr_proc, c_addr); return 1; }
int pr_IDListExpandedMembers(afs_int32 aid, namelist * lnames) { afs_int32 code; afs_int32 gid; idlist lids; prlist alist; afs_int32 over; struct idhash *members = NULL; afs_int32 *stack = NULL; afs_int32 maxstack = ID_STACK_SIZE; int n = 0; /* number of ids stacked */ int i; int firstpass = 1; code = AllocateIdHash(&members); if (code) { return code; } stack = malloc(sizeof(afs_int32) * maxstack); if (!stack) { code = ENOMEM; goto done; } stack[n++] = aid; while (n) { gid = stack[--n]; /* pop next group id */ alist.prlist_len = 0; alist.prlist_val = NULL; if (firstpass || aid < 0) { firstpass = 0; code = ubik_PR_ListElements(pruclient, 0, gid, &alist, &over); } else { code = ubik_PR_ListSuperGroups(pruclient, 0, gid, &alist, &over); if (code == RXGEN_OPCODE) { alist.prlist_len = 0; alist.prlist_val = NULL; code = 0; /* server does not support supergroups. */ } } if (code) goto done; if (over) { fprintf(stderr, "membership list for id %d exceeds display limit\n", gid); } for (i = 0; i < alist.prlist_len; i++) { afs_int32 found; afs_int32 id; id = alist.prlist_val[i]; found = FindId(members, id); if (found < 0) { code = found; xdr_free((xdrproc_t) xdr_prlist, &alist); goto done; } if (found == 0 && id < 0) { if (n == maxstack) { /* need more stack space */ afs_int32 *tmp; maxstack += n; tmp = realloc(stack, maxstack * sizeof(afs_int32)); if (!tmp) { code = ENOMEM; xdr_free((xdrproc_t) xdr_prlist, &alist); goto done; } stack = tmp; } stack[n++] = id; /* push group id */ } } xdr_free((xdrproc_t) xdr_prlist, &alist); } code = CreateIdList(members, &lids, (aid < 0 ? PRUSERS : PRGROUPS)); if (code) { goto done; } else if (lids.idlist_len == 0) { /* Avoid the RPC when there's nothing to look up. */ lnames->namelist_len = 0; lnames->namelist_val = NULL; goto done; } code = pr_IdToName(&lids, lnames); free(lids.idlist_val); done: if (stack) free(stack); if (members) FreeIdHash(members); return code; }
enum auth_stat gssrpc__svcauth_gssapi( register struct svc_req *rqst, register struct rpc_msg *msg, bool_t *no_dispatch) { XDR xdrs; auth_gssapi_creds creds; auth_gssapi_init_arg call_arg; auth_gssapi_init_res call_res; gss_buffer_desc output_token, in_buf, out_buf; gss_cred_id_t server_creds; struct gss_channel_bindings_struct bindings, *bindp; OM_uint32 gssstat, minor_stat, time_rec; struct opaque_auth *cred, *verf; svc_auth_gssapi_data *client_data; int i; enum auth_stat ret; OM_uint32 ret_flags; uint32_t seq_num; PRINTF(("svcauth_gssapi: starting\n")); /* clean up expired entries */ clean_client(); /* use AUTH_NONE until there is a client_handle */ rqst->rq_xprt->xp_auth = &svc_auth_none; memset((char *) &call_res, 0, sizeof(call_res)); creds.client_handle.length = 0; creds.client_handle.value = NULL; cred = &msg->rm_call.cb_cred; verf = &msg->rm_call.cb_verf; if (cred->oa_length == 0) { PRINTF(("svcauth_gssapi: empty creds, failing\n")); LOG_MISCERR("empty client credentials"); ret = AUTH_BADCRED; goto error; } PRINTF(("svcauth_gssapi: decoding credentials\n")); xdrmem_create(&xdrs, cred->oa_base, cred->oa_length, XDR_DECODE); memset((char *) &creds, 0, sizeof(creds)); if (! xdr_authgssapi_creds(&xdrs, &creds)) { PRINTF(("svcauth_gssapi: failed decoding creds\n")); LOG_MISCERR("protocol error in client credentials"); xdr_free(xdr_authgssapi_creds, &creds); XDR_DESTROY(&xdrs); ret = AUTH_BADCRED; goto error; } XDR_DESTROY(&xdrs); PRINTF(("svcauth_gssapi: got credentials, version %d, client_handle len %d\n", creds.version, (int) creds.client_handle.length)); if (creds.version != 2) { PRINTF(("svcauth_gssapi: bad credential version\n")); LOG_MISCERR("unsupported client credentials version"); ret = AUTH_BADCRED; goto error; } #ifdef DEBUG_GSSAPI if (svc_debug_gssapi) { if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_EXIT) { PRINTF(("svcauth_gssapi: GSSAPI_EXIT, cleaning up\n")); svc_sendreply(rqst->rq_xprt, xdr_void, NULL); xdr_free(xdr_authgssapi_creds, &creds); cleanup(); exit(0); } } #endif /* * If this is an auth_msg and proc is GSSAPI_INIT, then create a * client handle for this client. Otherwise, look up the * existing handle. */ if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_INIT) { if (creds.client_handle.length != 0) { PRINTF(("svcauth_gssapi: non-empty handle on GSSAPI_INIT\n")); LOG_MISCERR("protocol error in client handle"); ret = AUTH_FAILED; goto error; } PRINTF(("svcauth_gssapi: GSSAPI_INIT, creating client.\n")); client_data = create_client(); if (client_data == NULL) { PRINTF(("svcauth_gssapi: create_client failed\n")); LOG_MISCERR("internal error creating client record"); ret = AUTH_FAILED; goto error; } } else { if (creds.client_handle.length == 0) { PRINTF(("svcauth_gssapi: expected non-empty creds\n")); LOG_MISCERR("protocol error in client credentials"); ret = AUTH_FAILED; goto error; } PRINTF(("svcauth_gssapi: incoming client_handle %d, len %d\n", *((uint32_t *) creds.client_handle.value), (int) creds.client_handle.length)); client_data = get_client(&creds.client_handle); if (client_data == NULL) { PRINTF(("svcauth_gssapi: client_handle lookup failed\n")); LOG_MISCERR("invalid client handle received"); ret = AUTH_BADCRED; goto error; } PRINTF(("svcauth_gssapi: client_handle lookup succeeded\n")); } /* any response we send will use client_handle, so set it now */ call_res.client_handle.length = sizeof(client_data->key); call_res.client_handle.value = (char *) &client_data->key; /* mark this call as using AUTH_GSSAPI via client_data's SVCAUTH */ rqst->rq_xprt->xp_auth = &client_data->svcauth; if (client_data->established == FALSE) { PRINTF(("svcauth_gssapi: context is not established\n")); if (creds.auth_msg == FALSE) { PRINTF(("svcauth_gssapi: expected auth_msg TRUE\n")); LOG_MISCERR("protocol error on incomplete connection"); ret = AUTH_REJECTEDCRED; goto error; } /* * If the context is not established, then only GSSAPI_INIT * and _CONTINUE requests are valid. */ if (rqst->rq_proc != AUTH_GSSAPI_INIT && rqst->rq_proc != AUTH_GSSAPI_CONTINUE_INIT) { PRINTF(("svcauth_gssapi: unacceptable procedure %d\n", rqst->rq_proc)); LOG_MISCERR("protocol error on incomplete connection"); ret = AUTH_FAILED; goto error; } /* call is for us, deserialize arguments */ memset(&call_arg, 0, sizeof(call_arg)); if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg, &call_arg)) { PRINTF(("svcauth_gssapi: cannot decode args\n")); LOG_MISCERR("protocol error in procedure arguments"); ret = AUTH_BADCRED; goto error; } /* * Process the call arg version number. * * Set the krb5_gss backwards-compatibility mode based on client * version. This controls whether the AP_REP message is * encrypted with the session key (version 2+, correct) or the * session subkey (version 1, incorrect). This function can * never fail, so we don't bother checking its return value. */ switch (call_arg.version) { case 1: case 2: LOG_MISCERR("Warning: Accepted old RPC protocol request"); call_res.version = 1; break; case 3: case 4: /* 3 and 4 are essentially the same, don't bother warning */ call_res.version = call_arg.version; break; default: PRINTF(("svcauth_gssapi: bad GSSAPI_INIT version\n")); LOG_MISCERR("unsupported GSSAPI_INIT version"); ret = AUTH_BADCRED; goto error; } #ifdef GSS_BACKWARD_HACK krb5_gss_set_backward_mode(&minor_stat, call_arg.version == 1); #endif if (call_arg.version >= 3) { memset(&bindings, 0, sizeof(bindings)); bindings.application_data.length = 0; bindings.initiator_addrtype = GSS_C_AF_INET; bindings.initiator_address.length = 4; bindings.initiator_address.value = &svc_getcaller(rqst->rq_xprt)->sin_addr.s_addr; if (rqst->rq_xprt->xp_laddrlen > 0) { bindings.acceptor_addrtype = GSS_C_AF_INET; bindings.acceptor_address.length = 4; bindings.acceptor_address.value = &rqst->rq_xprt->xp_laddr.sin_addr.s_addr; } else { LOG_MISCERR("cannot get local address"); ret = AUTH_FAILED; goto error; } bindp = &bindings; } else { bindp = GSS_C_NO_CHANNEL_BINDINGS; } /* * If the client's server_creds is already set, use it. * Otherwise, try each credential in server_creds_list until * one of them succeedes, then set the client server_creds * to that. If all fail, the client's server_creds isn't * set (which is fine, because the client will be gc'ed * anyway). * * If accept_sec_context returns something other than * success and GSS_S_FAILURE, then assume different * credentials won't help and stop looping. * * Note that there are really two cases here: (1) the client * has a server_creds already, and (2) it does not. They * are both written in the same loop so that there is only * one textual call to gss_accept_sec_context; in fact, in * case (1), the loop is executed exactly once. */ for (i = 0; i < server_creds_count; i++) { if (client_data->server_creds != NULL) { PRINTF(("svcauth_gssapi: using's clients server_creds\n")); server_creds = client_data->server_creds; } else { PRINTF(("svcauth_gssapi: trying creds %d\n", i)); server_creds = server_creds_list[i]; } /* Free previous output_token from loop */ if(i != 0) gss_release_buffer(&minor_stat, &output_token); call_res.gss_major = gss_accept_sec_context(&call_res.gss_minor, &client_data->context, server_creds, &call_arg.token, bindp, &client_data->client_name, NULL, &output_token, &ret_flags, &time_rec, NULL); if (server_creds == client_data->server_creds) break; PRINTF(("accept_sec_context returned 0x%x 0x%x wrong-princ=%#x\n", call_res.gss_major, call_res.gss_minor, (int) KRB5KRB_AP_WRONG_PRINC)); if (call_res.gss_major == GSS_S_COMPLETE || call_res.gss_major == GSS_S_CONTINUE_NEEDED) { /* server_creds was right, set it! */ PRINTF(("svcauth_gssapi: creds are correct, storing\n")); client_data->server_creds = server_creds; client_data->server_name = server_name_list[i]; break; } else if (call_res.gss_major != GSS_S_FAILURE #ifdef GSSAPI_KRB5 /* * hard-coded because there is no other way * to prevent all GSS_S_FAILURES from * returning a "wrong principal in request" * error */ || ((krb5_error_code) call_res.gss_minor != (krb5_error_code) KRB5KRB_AP_WRONG_PRINC) #endif ) { break; } } gssstat = call_res.gss_major; minor_stat = call_res.gss_minor; /* done with call args */ xdr_free(xdr_authgssapi_init_arg, &call_arg); PRINTF(("svcauth_gssapi: accept_sec_context returned %#x %#x\n", call_res.gss_major, call_res.gss_minor)); if (call_res.gss_major != GSS_S_COMPLETE && call_res.gss_major != GSS_S_CONTINUE_NEEDED) { AUTH_GSSAPI_DISPLAY_STATUS(("accepting context", call_res.gss_major, call_res.gss_minor)); if (log_badauth != NULL) (*log_badauth)(call_res.gss_major, call_res.gss_minor, &rqst->rq_xprt->xp_raddr, log_badauth_data); gss_release_buffer(&minor_stat, &output_token); svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res, (caddr_t) &call_res); *no_dispatch = TRUE; ret = AUTH_OK; goto error; } if (output_token.length != 0) { PRINTF(("svcauth_gssapi: got new output token\n")); GSS_COPY_BUFFER(call_res.token, output_token); } if (gssstat == GSS_S_COMPLETE) { client_data->seq_num = rand(); client_expire(client_data, (time_rec == GSS_C_INDEFINITE ? INDEF_EXPIRE : time_rec) + time(0)); PRINTF(("svcauth_gssapi: context established, isn %d\n", client_data->seq_num)); if (auth_gssapi_seal_seq(client_data->context, client_data->seq_num, &call_res.signed_isn) == FALSE) { ret = AUTH_FAILED; LOG_MISCERR("internal error sealing sequence number"); gss_release_buffer(&minor_stat, &output_token); goto error; } } PRINTF(("svcauth_gssapi: sending reply\n")); svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res, (caddr_t) &call_res); *no_dispatch = TRUE; /* * If appropriate, set established to TRUE *after* sending * response (otherwise, the client will receive the final * token encrypted) */ if (gssstat == GSS_S_COMPLETE) { gss_release_buffer(&minor_stat, &call_res.signed_isn); client_data->established = TRUE; } gss_release_buffer(&minor_stat, &output_token); } else { PRINTF(("svcauth_gssapi: context is established\n")); /* check the verifier */ PRINTF(("svcauth_gssapi: checking verifier, len %d\n", verf->oa_length)); in_buf.length = verf->oa_length; in_buf.value = verf->oa_base; if (auth_gssapi_unseal_seq(client_data->context, &in_buf, &seq_num) == FALSE) { ret = AUTH_BADVERF; LOG_MISCERR("internal error unsealing sequence number"); goto error; } if (seq_num != client_data->seq_num + 1) { PRINTF(("svcauth_gssapi: expected isn %d, got %d\n", client_data->seq_num + 1, seq_num)); if (log_badverf != NULL) (*log_badverf)(client_data->client_name, client_data->server_name, rqst, msg, log_badverf_data); ret = AUTH_REJECTEDVERF; goto error; } client_data->seq_num++; PRINTF(("svcauth_gssapi: seq_num %d okay\n", seq_num)); /* free previous response verifier, if any */ if (client_data->prev_verf.length != 0) { gss_release_buffer(&minor_stat, &client_data->prev_verf); client_data->prev_verf.length = 0; } /* prepare response verifier */ seq_num = client_data->seq_num + 1; if (auth_gssapi_seal_seq(client_data->context, seq_num, &out_buf) == FALSE) { ret = AUTH_FAILED; LOG_MISCERR("internal error sealing sequence number"); goto error; } client_data->seq_num++; PRINTF(("svcauth_gssapi; response seq_num %d\n", seq_num)); rqst->rq_xprt->xp_verf.oa_flavor = AUTH_GSSAPI; rqst->rq_xprt->xp_verf.oa_base = out_buf.value; rqst->rq_xprt->xp_verf.oa_length = out_buf.length; /* save verifier so it can be freed next time */ client_data->prev_verf.value = out_buf.value; client_data->prev_verf.length = out_buf.length; /* * Message is authentic. If auth_msg if true, process the * call; otherwise, return AUTH_OK so it will be dispatched * to the application server. */ if (creds.auth_msg == TRUE) { /* * If process_token fails, then the token probably came * from an attacker. No response (error or otherwise) * should be returned to the client, since it won't be * accepting one. */ switch (rqst->rq_proc) { case AUTH_GSSAPI_MSG: PRINTF(("svcauth_gssapi: GSSAPI_MSG, getting args\n")); memset(&call_arg, 0, sizeof(call_arg)); if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg, &call_arg)) { PRINTF(("svcauth_gssapi: cannot decode args\n")); LOG_MISCERR("protocol error in call arguments"); xdr_free(xdr_authgssapi_init_arg, &call_arg); ret = AUTH_BADCRED; goto error; } PRINTF(("svcauth_gssapi: processing token\n")); gssstat = gss_process_context_token(&minor_stat, client_data->context, &call_arg.token); /* done with call args */ xdr_free(xdr_authgssapi_init_arg, &call_arg); if (gssstat != GSS_S_COMPLETE) { AUTH_GSSAPI_DISPLAY_STATUS(("processing token", gssstat, minor_stat)); ret = AUTH_FAILED; goto error; } svc_sendreply(rqst->rq_xprt, xdr_void, NULL); *no_dispatch = TRUE; break; case AUTH_GSSAPI_DESTROY: PRINTF(("svcauth_gssapi: GSSAPI_DESTROY\n")); PRINTF(("svcauth_gssapi: sending reply\n")); svc_sendreply(rqst->rq_xprt, xdr_void, NULL); *no_dispatch = TRUE; destroy_client(client_data); rqst->rq_xprt->xp_auth = NULL; break; default: PRINTF(("svcauth_gssapi: unacceptable procedure %d\n", rqst->rq_proc)); LOG_MISCERR("invalid call procedure number"); ret = AUTH_FAILED; goto error; } } else { /* set credentials for app server; comment in svc.c */ /* seems to imply this is incorrect, but I don't see */ /* any problem with it... */ rqst->rq_clntcred = (char *)client_data->client_name; rqst->rq_svccred = (char *)client_data->context; } } if (creds.client_handle.length != 0) { PRINTF(("svcauth_gssapi: freeing client_handle len %d\n", (int) creds.client_handle.length)); xdr_free(xdr_authgssapi_creds, &creds); } PRINTF(("\n")); return AUTH_OK; error: if (creds.client_handle.length != 0) { PRINTF(("svcauth_gssapi: freeing client_handle len %d\n", (int) creds.client_handle.length)); xdr_free(xdr_authgssapi_creds, &creds); } PRINTF(("\n")); return ret; }
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) { struct init_sec_context_res res; struct init_sec_context_args args; enum clnt_stat stat; gss_ctx_id_t ctx = *context_handle; *minor_status = 0; if (!kgss_gssd_handle) return (GSS_S_FAILURE); args.uid = curthread->td_ucred->cr_uid; if (initiator_cred_handle) args.cred = initiator_cred_handle->handle; else args.cred = 0; if (ctx) args.ctx = ctx->handle; else args.ctx = 0; args.name = target_name->handle; args.mech_type = input_mech_type; args.req_flags = req_flags; args.time_req = time_req; args.input_chan_bindings = input_chan_bindings; if (input_token) args.input_token = *input_token; else { args.input_token.length = 0; args.input_token.value = NULL; } bzero(&res, sizeof(res)); stat = gssd_init_sec_context_1(&args, &res, kgss_gssd_handle); if (stat != RPC_SUCCESS) { *minor_status = stat; return (GSS_S_FAILURE); } if (res.major_status != GSS_S_COMPLETE && res.major_status != GSS_S_CONTINUE_NEEDED) { *minor_status = res.minor_status; xdr_free((xdrproc_t) xdr_init_sec_context_res, &res); return (res.major_status); } *minor_status = res.minor_status; if (!ctx) { ctx = kgss_create_context(res.actual_mech_type); if (!ctx) { xdr_free((xdrproc_t) xdr_init_sec_context_res, &res); *minor_status = 0; return (GSS_S_BAD_MECH); } } *context_handle = ctx; ctx->handle = res.ctx; if (actual_mech_type) *actual_mech_type = KGSS_MECH_TYPE(ctx); kgss_copy_buffer(&res.output_token, output_token); if (ret_flags) *ret_flags = res.ret_flags; if (time_rec) *time_rec = res.time_rec; xdr_free((xdrproc_t) xdr_init_sec_context_res, &res); /* * If the context establishment is complete, export it from * userland and hand the result (which includes key material * etc.) to the kernel implementation. */ if (res.major_status == GSS_S_COMPLETE) res.major_status = kgss_transfer_context(ctx); return (res.major_status); }
/* Return -1 on error, 0 otherwise */ int sfs_stat2names (sfs_names *snp, const struct stat *sb) { const char *fs; int cdfd; sfsctl_getidnames_res res; struct passwd *pw; struct group *gr; bool_t remote = FALSE; bool_t uname = FALSE; bool_t gname = FALSE; struct id_dat *id_elm; struct id_cache *ic; u_int hval; ic = lookup_ic (sb->st_dev); if (!ic) return -1; for (id_elm = id2name_chain (&ic->uidtab, sb->st_uid); id_elm && (sb->st_uid != id_elm->id); id_elm = id2name_next (id_elm)) ; if (id_elm) { namecpy (snp->uidname, id_elm->name); uname = TRUE; } for (id_elm = id2name_chain (&ic->gidtab, sb->st_gid); id_elm && (sb->st_gid != id_elm->id); id_elm = id2name_next (id_elm)) ; if (id_elm) { namecpy (snp->gidname, id_elm->name); gname = TRUE; } if (gname && uname) return 0; bzero (&res, sizeof (res)); if (devcon_lookup (&cdfd, &fs, sb->st_dev)) { sfsctl_getidnames_arg arg; remote = TRUE; arg.filesys = (char *) fs; arg.nums.uid = sb->st_uid; arg.nums.gid = sb->st_gid; srpc_call (&sfsctl_prog_1, cdfd, SFSCTL_GETIDNAMES, &arg, &res); } if (!uname) { pw = getpwuid (sb->st_uid); if (remote && !res.status && res.u.names.uidname.present) { if (pw && !strcmp (pw->pw_name, res.u.names.uidname.u.name)) namecpy (snp->uidname, pw->pw_name); else { snp->uidname[0] = '%'; namecpy (snp->uidname + 1, res.u.names.uidname.u.name); } } else if (!remote && pw) namecpy (snp->uidname, pw->pw_name); else sprintf (snp->uidname, "%u", (int) sb->st_uid); id_elm = malloc (sizeof (*id_elm)); if (!id_elm) { xdr_free ((xdrproc_t) xdr_sfsctl_getidnames_res, (char *) &res); return -1; } bzero (id_elm->name, sizeof (id_elm->name)); namecpy (id_elm->name, snp->uidname); id_elm->id = sb->st_uid; hval = hash_string (id_elm->name); id2name_insert (&ic->uidtab, id_elm, id_elm->id); name2id_insert (&ic->unametab, id_elm, hval); } if (!gname) { gr = getgrgid (sb->st_gid); if (remote && !res.status && res.u.names.gidname.present) { if (gr && !strcmp (gr->gr_name, res.u.names.gidname.u.name)) namecpy (snp->gidname, gr->gr_name); else { snp->gidname[0] = '%'; namecpy (snp->gidname + 1, res.u.names.gidname.u.name); } } else if (!remote && gr) namecpy (snp->gidname, gr->gr_name); else sprintf (snp->gidname, "%u", (int) sb->st_gid); id_elm = malloc (sizeof (*id_elm)); if (!id_elm) { xdr_free ((xdrproc_t) xdr_sfsctl_getidnames_res, (char *) &res); return -1; } bzero (id_elm->name, sizeof (id_elm->name)); namecpy (id_elm->name, snp->gidname); id_elm->id = sb->st_gid; hval = hash_string (id_elm->name); id2name_insert (&ic->gidtab, id_elm, id_elm->id); name2id_insert (&ic->gnametab, id_elm, hval); } xdr_free ((xdrproc_t) xdr_sfsctl_getidnames_res, (char *) &res); return 0; }
int lookup_id (struct id_cache *ic, bool_t gid, char *name) { struct id_dat *id_elm; char *orig_name = name; const char *fs; int cdfd; u_int hval; if (*name == '%') name++; hval = hash_string (name); for (id_elm = name2id_chain ((gid ? &ic->gnametab : &ic->unametab), hval); id_elm && strcmp (name, id_elm->name); id_elm = name2id_next (id_elm)) ; if (id_elm) return id_elm->id; id_elm = malloc (sizeof (*id_elm)); if (!id_elm) return -1; bzero (id_elm->name, sizeof (id_elm->name)); namecpy (id_elm->name, name); name = orig_name; /* Get the id either locally or via SFS */ if (*name != '%' || (++name, !devcon_lookup (&cdfd, &fs, ic->dev))) { if (gid) { struct group *gr = getgrnam (name); if (gr) id_elm->id = gr->gr_gid; else id_elm->id = -1; } else { struct passwd *pw = getpwnam (name); if (pw) id_elm->id = pw->pw_uid; else id_elm->id = -1; } } else if (strlen (name) > sfs_idnamelen) { free (id_elm); return -1; } else { sfsctl_getidnums_arg arg; sfsctl_getidnums_res res; sfs_opt_idname *sid; bzero (&arg, sizeof (arg)); bzero (&res, sizeof (res)); arg.filesys = (char *) fs; sid = gid ? &arg.names.gidname : &arg.names.uidname; sid->present = TRUE; sid->u.name = (char *) name; srpc_call (&sfsctl_prog_1, cdfd, SFSCTL_GETIDNUMS, &arg, &res); if (!res.status) id_elm->id = gid ? res.u.nums.gid : res.u.nums.uid; else { free (id_elm); xdr_free ((xdrproc_t) xdr_sfsctl_getidnums_res, (char *) &res); return -1; } xdr_free ((xdrproc_t) xdr_sfsctl_getidnums_res, (char *) &res); } id2name_insert (gid ? &ic->gidtab : &ic->uidtab, id_elm, id_elm->id); name2id_insert (gid ? &ic->gnametab : &ic->unametab, id_elm, hval); return id_elm->id; }
/** Application callBack: THis the callback that is activated upon the recption of an exportd request from a rozofsmount client @param socket_ctx_p: pointer to the af unix socket @param socketId: reference of the socket (not used) @retval : TRUE-> xmit ready event expected @retval : FALSE-> xmit ready event not expected */ void expgw_rozofs_req_rcv_cbk(void *userRef,uint32_t socket_ctx_idx, void *recv_buf) { uint32_t *com_hdr_p; rozofs_rpc_call_hdr_t hdr; expgw_ctx_t *expgw_ctx_p = NULL; com_hdr_p = (uint32_t*) ruc_buf_getPayload(recv_buf); com_hdr_p +=1; /* skip the size of the rpc message */ memcpy(&hdr,com_hdr_p,sizeof(rozofs_rpc_call_hdr_t)); scv_call_hdr_ntoh(&hdr); /* ** allocate a context for the duration of the transaction since it might be possible ** that the gateway needs to interrogate the exportd and thus needs to save the current ** request until receiving the response from the exportd */ expgw_ctx_p = expgw_alloc_context(); if (expgw_ctx_p == NULL) { fatal(" Out of exportd gateway context"); } /* ** save the initial transaction id, received buffer and reference of the connection */ expgw_ctx_p->src_transaction_id = hdr.hdr.xid; expgw_ctx_p->recv_buf = recv_buf; expgw_ctx_p->socketRef = socket_ctx_idx; union { ep_path_t ep_mount_1_arg; uint32_t ep_umount_1_arg; uint32_t ep_statfs_1_arg; epgw_lookup_arg_t ep_lookup_1_arg; epgw_mfile_arg_t ep_getattr_1_arg; epgw_setattr_arg_t ep_setattr_1_arg; epgw_mfile_arg_t ep_readlink_1_arg; epgw_mknod_arg_t ep_mknod_1_arg; epgw_mkdir_arg_t ep_mkdir_1_arg; epgw_unlink_arg_t ep_unlink_1_arg; epgw_rmdir_arg_t ep_rmdir_1_arg; epgw_symlink_arg_t ep_symlink_1_arg; epgw_rename_arg_t ep_rename_1_arg; epgw_readdir_arg_t ep_readdir_1_arg; epgw_io_arg_t ep_read_block_1_arg; epgw_write_block_arg_t ep_write_block_1_arg; epgw_link_arg_t ep_link_1_arg; epgw_setxattr_arg_t ep_setxattr_1_arg; epgw_getxattr_arg_t ep_getxattr_1_arg; epgw_removexattr_arg_t ep_removexattr_1_arg; epgw_listxattr_arg_t ep_listxattr_1_arg; uint16_t ep_list_cluster_1_arg; } argument; xdrproc_t _xdr_argument, _xdr_result; char *(*local)(char *, struct svc_req *); switch (hdr.proc) { #if 0 case EP_NULL: _xdr_argument = (xdrproc_t) xdr_void; _xdr_result = (xdrproc_t) xdr_void; local = (char *(*)(char *, struct svc_req *)) ep_null_1_svc; break; case EP_MOUNT: _xdr_argument = (xdrproc_t) xdr_ep_path_t; _xdr_result = (xdrproc_t) xdr_ep_mount_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_mount_1_svc; break; case EP_UMOUNT: _xdr_argument = (xdrproc_t) xdr_uint32_t; _xdr_result = (xdrproc_t) xdr_epgw_status_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_umount_1_svc; break; case EP_STATFS: _xdr_argument = (xdrproc_t) xdr_uint32_t; _xdr_result = (xdrproc_t) xdr_ep_statfs_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_statfs_1_svc; break; #endif case EP_LOOKUP: START_PROFILING_EXPGW(expgw_ctx_p,ep_lookup); _xdr_argument = (xdrproc_t) xdr_epgw_lookup_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_mattr_ret_t; local = (char *(*)(char *, struct svc_req *)) expgw_lookup_1_svc; break; case EP_GETATTR: START_PROFILING_EXPGW(expgw_ctx_p,ep_getattr); _xdr_argument = (xdrproc_t) xdr_epgw_mfile_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_mattr_ret_t; local = (char *(*)(char *, struct svc_req *)) expgw_getattr_1_svc; break; case EP_SETATTR: START_PROFILING_EXPGW(expgw_ctx_p,ep_setattr); _xdr_argument = (xdrproc_t) xdr_epgw_setattr_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_mattr_ret_t; local = (char *(*)(char *, struct svc_req *)) expgw_setattr_1_svc; break; #if 0 case EP_READLINK: START_PROFILING_EXPGW(expgw_ctx_p,ep_readlink); _xdr_argument = (xdrproc_t) xdr_ep_mfile_arg_t; _xdr_result = (xdrproc_t) xdr_ep_readlink_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_readlink_1_svc; break; #endif case EP_MKNOD: START_PROFILING_EXPGW(expgw_ctx_p,ep_mknod); _xdr_argument = (xdrproc_t) xdr_epgw_mknod_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_mattr_ret_t; local = (char *(*)(char *, struct svc_req *)) expgw_mknod_1_svc; break; case EP_MKDIR: START_PROFILING_EXPGW(expgw_ctx_p,ep_mkdir); _xdr_argument = (xdrproc_t) xdr_epgw_mkdir_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_mattr_ret_t; local = (char *(*)(char *, struct svc_req *)) expgw_mkdir_1_svc; break; case EP_UNLINK: START_PROFILING_EXPGW(expgw_ctx_p,ep_unlink); _xdr_argument = (xdrproc_t) xdr_epgw_unlink_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_fid_ret_t; local = (char *(*)(char *, struct svc_req *)) expgw_unlink_1_svc; break; case EP_RMDIR: START_PROFILING_EXPGW(expgw_ctx_p,ep_rmdir); _xdr_argument = (xdrproc_t) xdr_epgw_rmdir_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_fid_ret_t; local = (char *(*)(char *, struct svc_req *)) expgw_rmdir_1_svc; break; case EP_SYMLINK: START_PROFILING_EXPGW(expgw_ctx_p,ep_symlink); _xdr_argument = (xdrproc_t) xdr_epgw_symlink_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_mattr_ret_t; local = (char *(*)(char *, struct svc_req *)) expgw_symlink_1_svc; break; #if 0 case EP_RENAME: START_PROFILING_EXPGW(expgw_ctx_p,ep_rename); _xdr_argument = (xdrproc_t) xdr_ep_rename_arg_t; _xdr_result = (xdrproc_t) xdr_ep_fid_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_rename_1_svc; break; case EP_READDIR: START_PROFILING_EXPGW(expgw_ctx_p,ep_readdir); _xdr_argument = (xdrproc_t) xdr_ep_readdir_arg_t; _xdr_result = (xdrproc_t) xdr_ep_readdir_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_readdir_1_svc; break; case EP_READ_BLOCK: START_PROFILING_EXPGW(expgw_ctx_p,ep_read_block); _xdr_argument = (xdrproc_t) xdr_ep_io_arg_t; _xdr_result = (xdrproc_t) xdr_ep_read_block_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_read_block_1_svc; break; #endif case EP_WRITE_BLOCK: START_PROFILING_EXPGW(expgw_ctx_p,ep_write_block); _xdr_argument = (xdrproc_t) xdr_epgw_write_block_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_mattr_ret_t; local = (char *(*)(char *, struct svc_req *)) expgw_write_block_1_svc; break; case EP_LINK: START_PROFILING_EXPGW(expgw_ctx_p,ep_link); _xdr_argument = (xdrproc_t) xdr_epgw_link_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_mattr_ret_t; local = (char *(*)(char *, struct svc_req *)) expgw_link_1_svc; break; #if 0 case EP_SETXATTR: START_PROFILING_EXPGW(expgw_ctx_p,ep_setxattr); _xdr_argument = (xdrproc_t) xdr_ep_setxattr_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_status_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_setxattr_1_svc; break; case EP_GETXATTR: START_PROFILING_EXPGW(expgw_ctx_p,ep_getxattr); _xdr_argument = (xdrproc_t) xdr_ep_getxattr_arg_t; _xdr_result = (xdrproc_t) xdr_ep_getxattr_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_getxattr_1_svc; break; case EP_REMOVEXATTR: START_PROFILING_EXPGW(expgw_ctx_p,ep_removexattr); _xdr_argument = (xdrproc_t) xdr_ep_removexattr_arg_t; _xdr_result = (xdrproc_t) xdr_epgw_status_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_removexattr_1_svc; break; case EP_LISTXATTR: START_PROFILING_EXPGW(expgw_ctx_p,ep_listxattr); _xdr_argument = (xdrproc_t) xdr_ep_listxattr_arg_t; _xdr_result = (xdrproc_t) xdr_ep_listxattr_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_listxattr_1_svc; break; case EP_LIST_CLUSTER: _xdr_argument = (xdrproc_t) xdr_uint16_t; _xdr_result = (xdrproc_t) xdr_ep_cluster_ret_t; local = (char *(*)(char *, struct svc_req *)) ep_list_cluster_1_svc; break; #endif default: expgw_ctx_p->xmitBuf = expgw_ctx_p->recv_buf; expgw_ctx_p->recv_buf = NULL; errno = EPROTO; expgw_reply_error(expgw_ctx_p,errno); expgw_release_context(expgw_ctx_p); return; } memset ((char *)&argument, 0, sizeof (argument)); /* ** save the result encoding/decoding function */ expgw_ctx_p->xdr_result = _xdr_result; if (!expgw_getargs (recv_buf, (xdrproc_t) _xdr_argument, (caddr_t) &argument)) { expgw_ctx_p->xmitBuf = expgw_ctx_p->recv_buf; expgw_ctx_p->recv_buf = NULL; expgw_reply_error(expgw_ctx_p,errno); /* ** release the context */ xdr_free((xdrproc_t)_xdr_argument, (caddr_t) &argument); expgw_release_context(expgw_ctx_p); return; } /* ** call the user call-back */ (*local)((char *)&argument, (void*)expgw_ctx_p); /* ** release any data allocated while decoding */ xdr_free((xdrproc_t)_xdr_argument, (caddr_t) &argument); }
bool_t xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop, rpc_gss_service_t svc, u_int seq) { XDR tmpxdrs; gss_buffer_desc databuf, wrapbuf; OM_uint32 maj_stat, min_stat; u_int seq_num, conf_state, qop_state; bool_t xdr_stat; if (xdr_func == (xdrproc_t) xdr_void || xdr_ptr == NULL) return (TRUE); memset(&databuf, 0, sizeof(databuf)); memset(&wrapbuf, 0, sizeof(wrapbuf)); if (svc == rpc_gss_svc_integrity) { /* Decode databody_integ. */ if (!xdr_gss_buffer_desc(xdrs, &databuf)) { log_debug("xdr decode databody_integ failed"); return (FALSE); } /* Decode checksum. */ if (!xdr_gss_buffer_desc(xdrs, &wrapbuf)) { mem_free(databuf.value, databuf.length); log_debug("xdr decode checksum failed"); return (FALSE); } /* Verify checksum and QOP. */ maj_stat = gss_verify_mic(&min_stat, ctx, &databuf, &wrapbuf, &qop_state); mem_free(wrapbuf.value, wrapbuf.length); if (maj_stat != GSS_S_COMPLETE || qop_state != qop) { mem_free(databuf.value, databuf.length); log_status("gss_verify_mic", NULL, maj_stat, min_stat); return (FALSE); } } else if (svc == rpc_gss_svc_privacy) { /* Decode databody_priv. */ if (!xdr_gss_buffer_desc(xdrs, &wrapbuf)) { log_debug("xdr decode databody_priv failed"); return (FALSE); } /* Decrypt databody. */ maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf, &conf_state, &qop_state); mem_free(wrapbuf.value, wrapbuf.length); /* Verify encryption and QOP. */ if (maj_stat != GSS_S_COMPLETE || qop_state != qop || conf_state != TRUE) { gss_release_buffer(&min_stat, &databuf); log_status("gss_unwrap", NULL, maj_stat, min_stat); return (FALSE); } } /* Decode rpc_gss_data_t (sequence number + arguments). */ xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE); xdr_stat = (xdr_u_int(&tmpxdrs, &seq_num) && xdr_func(&tmpxdrs, xdr_ptr)); XDR_DESTROY(&tmpxdrs); /* * Integrity service allocates databuf via XDR so free it the * same way. */ if (svc == rpc_gss_svc_integrity) { xdr_free((xdrproc_t) xdr_gss_buffer_desc, (char *) &databuf); } else { gss_release_buffer(&min_stat, &databuf); } /* Verify sequence number. */ if (xdr_stat == TRUE && seq_num != seq) { log_debug("wrong sequence number in databody"); return (FALSE); } return (xdr_stat); }
Estado * borrarasociacion_1_svc(ID arg1, Clave arg2, struct svc_req *rqstp) { static Estado result; if(root==NULL) { // No hay ningún diccionario result = FALLO; } else { // Hay algún diccionario DiccionarioPtr dicPtr = root; bool encontradoID = false; if(dicPtr->id==arg1) { encontradoID = true; } if(encontradoID==true) { // Es el primer diccionario EntradaPtr entPtr = dicPtr->first; bool encontradoClave = false; if(strcmp(entPtr->clave,arg2)==0) { encontradoClave = true; } if(encontradoClave==true) { // Es la primera clave if(entPtr->sig==NULL) { // Es la unica clave root = dicPtr->sig; dicPtr->sig = NULL; xdr_free((xdrproc_t)xdr_Diccionario,(char*)dicPtr); result = OK; } else { // No es la unica clave dicPtr->first = entPtr->sig; entPtr->sig = NULL; xdr_free((xdrproc_t)xdr_Entrada,(char*)entPtr); result = OK; } } else { // No es la primera asociacion EntradaPtr entPtrAnt = entPtr; while(encontradoClave==false && entPtr->sig!=NULL) { // Buscar entrada entPtrAnt = entPtr; entPtr = entPtr->sig; if(strcmp(entPtr->clave,arg2)==0) { encontradoClave = true; } } if(encontradoClave==true) { // Clave encontrada entPtrAnt->sig = entPtr->sig; entPtr->sig = NULL; xdr_free((xdrproc_t)xdr_Entrada,(char*)entPtr); result = OK; } else { // Clave no encontrada result = FALLO; } } } else { // No es el primer diccionario DiccionarioPtr dicPtrAnt; while(encontradoID==false && dicPtr->sig!=NULL) { // Buscar diccionario dicPtrAnt = dicPtr; dicPtr = dicPtr->sig; if(dicPtr->id==arg1) { encontradoID = true; } } if(encontradoID==true) { // Diccionario encontrado EntradaPtr entPtr = dicPtr->first; bool encontradoClave = false; if(strcmp(entPtr->clave,arg2)==0) { encontradoClave = true; } if(encontradoClave==true) { // Es la primera clave if(entPtr->sig==NULL) { // Es la unica clave dicPtrAnt->sig = dicPtr->sig; dicPtr->sig = NULL; xdr_free((xdrproc_t)xdr_Diccionario,(char*)dicPtr); result = OK; } else { // No es la unica clave dicPtr->first = entPtr->sig; entPtr->sig = NULL; xdr_free((xdrproc_t)xdr_Entrada,(char*)entPtr); result = OK; } } else { // No es la primera asociacion EntradaPtr entPtrAnt = entPtr; while(encontradoClave==false && entPtr->sig!=NULL) { // Buscar entrada entPtrAnt = entPtr; entPtr = entPtr->sig; if(strcmp(entPtr->clave,arg2)==0) { encontradoClave = true; } } if(encontradoClave==true) { // Clave encontrada entPtrAnt->sig = entPtr->sig; entPtr->sig = NULL; xdr_free((xdrproc_t)xdr_Entrada,(char*)entPtr); result = OK; } else { // Clave no encontrada result = FALLO; } } } else { // Diccionario no encontrado result = FALLO; } } } return &result; }
RFSnfsReadDirectory(LPCLIENT ClientPointer, nfs_fh *NfsDirectoryHandlePointer, RFSItemSize ChunkSize, RFSnfsRDCallBack CallBackFunc, LPVOID CallBackParam, nfscookie *CookiePointer, LPRFSBool CallMeAgainPointer, LPRFSBool AnEntryFoundPointer) { RFSBool CallBackStatus; RFSnfsStatus YerStatus; readdirres *results; readdirargs *argumentsPointer; /* 40 bytes */ entry *entry_p; argumentsPointer = (readdirargs *)calloc(1, sizeof(readdirargs)); if (argumentsPointer == NULL) return RFSnfsNullResult; ClearNBlock(argumentsPointer, sizeof(readdirargs)); readdirargsDirectoryHandle(argumentsPointer) = *NfsDirectoryHandlePointer; CopyCookie(readdirargsCookie(argumentsPointer), *CookiePointer); readdirargsCount(argumentsPointer) = ChunkSize; *AnEntryFoundPointer = RFSFalse; *CallMeAgainPointer = RFSFalse; results = nfsproc_readdir_2_clnt(argumentsPointer, ClientPointer); free(argumentsPointer); if (results == NULL) { return(RFSnfsNullResult); } YerStatus = NfsToRFSnfs(readdirresStatus(results)); if ((readdirresStatus(results)) != NFS_OK) { xdr_free(xdr_readdirres, (char *)results); return YerStatus; } /* loop through all the returned entries and call the */ /* callback once for each entry. */ entry_p = readdirresFirstEntry(results); while (entry_p != NULL) { *AnEntryFoundPointer = RFSTrue; /* we saw an entry */ CopyCookie(*CookiePointer, entry_p->cookie); CallBackStatus = (*CallBackFunc)(entry_p->name, entry_p->cookie, CallBackParam); if (CallBackStatus != RFSTrue) { xdr_free(xdr_readdirres, (char *)results); return RFSCallBackError; } entry_p = entry_p->nextentry; } /* for all directory entries */ /* If we didn't hit the EOF then we want to be called again. */ if (readdirresEOF(results) != TRUE) *CallMeAgainPointer = RFSTrue; xdr_free(xdr_readdirres, (char *)results); return RFSNFS_OK; } /* RFSnfsReadDirectory */
int yp_match(const char *indomain, const char *inmap, const char *inkey, int inkeylen, char **outval, int *outvallen) { struct dom_binding *ysd; struct ypresp_val yprv; struct ypreq_key yprk; int r, nerrs = 0; if (outval == NULL || outvallen == NULL) return YPERR_BADARGS; *outval = NULL; *outvallen = 0; if (_yp_invalid_domain(indomain)) return YPERR_BADARGS; if (inmap == NULL || *inmap == '\0' || strlen(inmap) > YPMAXMAP) return YPERR_BADARGS; if (inkey == NULL || inkeylen == 0) return YPERR_BADARGS; again: if (_yp_dobind(indomain, &ysd) != 0) return YPERR_DOMAIN; #ifdef YPMATCHCACHE if (!strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey, inkeylen, &yprv.valdat.dptr, &yprv.valdat.dsize)) { *outvallen = yprv.valdat.dsize; if ((*outval = malloc((size_t)(*outvallen + 1))) == NULL) return YPERR_YPERR; (void)memcpy(*outval, yprv.valdat.dptr, (size_t)*outvallen); (*outval)[*outvallen] = '\0'; return 0; } #endif yprk.domain = indomain; yprk.map = inmap; yprk.keydat.dptr = __UNCONST(inkey); yprk.keydat.dsize = inkeylen; memset(&yprv, 0, sizeof yprv); r = clnt_call(ysd->dom_client, (rpcproc_t)YPPROC_MATCH, (xdrproc_t)xdr_ypreq_key, &yprk, (xdrproc_t)xdr_ypresp_val, &yprv, _yplib_timeout); if (r != RPC_SUCCESS) { if (_yplib_bindtries <= 0 && ++nerrs == _yplib_nerrs) { clnt_perror(ysd->dom_client, "yp_match: clnt_call"); nerrs = 0; } else if (_yplib_bindtries > 0 && ++nerrs == _yplib_bindtries) { return YPERR_YPSERV; } ysd->dom_vers = -1; goto again; } if (!(r = ypprot_err(yprv.status))) { *outvallen = yprv.valdat.dsize; if ((*outval = malloc((size_t)(*outvallen + 1))) == NULL) return YPERR_YPERR; (void)memcpy(*outval, yprv.valdat.dptr, (size_t)*outvallen); (*outval)[*outvallen] = '\0'; #ifdef YPMATCHCACHE if (strcmp(_yp_domain, indomain) == 0) if (!ypmatch_add(inmap, inkey, inkeylen, *outval, *outvallen)) r = YPERR_RESRC; #endif } xdr_free((xdrproc_t)xdr_ypresp_val, (char *)(void *)&yprv); __yp_unbind(ysd); if (r != 0) { if (*outval) { free(*outval); *outval = NULL; } } return r; }
RFSnfsRead(LPCLIENT ClientPointer, nfs_fh *NfsFileHandlePointer, RFSOffset Offset, RFSItemCount Count, LPRFSItemCount CountActuallyReadPointer, LPRFSItemCount FileSizePointer, char Buffer[]) { RFSnfsStatus ReturnStatus; readres * results; readargs *argumentsPointer; /* 44 bytes */ argumentsPointer = (readargs *)calloc(1, sizeof(readargs)); if (argumentsPointer == NULL) return RFSnfsNullResult; ClearNBlock(argumentsPointer, sizeof(readargs)); CopyNfsFileHandle(readargsFileHandle(argumentsPointer), *NfsFileHandlePointer); readargsOffset(argumentsPointer) = Offset; readargsCount(argumentsPointer) = Count; results = nfsproc_read_2_clnt(argumentsPointer, ClientPointer); free(argumentsPointer); if (results == NULL) { return(RFSnfsNullResult); } ReturnStatus = NfsToRFSnfs(readresStatus(results)); if ((readresStatus(results)) == NFS_OK) { *FileSizePointer = readresFileSize(results); *CountActuallyReadPointer = readresCount(results); /************************ BM KLUDGE ********************************/ /************************ BM KLUDGE ********************************/ /************************ BM KLUDGE ********************************/ /************************ BM KLUDGE ********************************/ /************************ BM KLUDGE ********************************/ /************************ BM KLUDGE ********************************/ #ifdef PNVMS_PLATFORM_WIN16 if ((readresCount(results)) > 65535) ReturnStatus = RFSNFSERR_IO; else #endif /* PNVMS_PLATFORM_WIN16 */ /* * The following memory operation requires that the 3rd parameter be * no larger than size_t (unsigned int) for the 16-bit compiler. If * we start using more sophisticated Windows memory operations that * allow moving larger amounts of memory, we can change this. For now, * we don't anticipate large buffers (>64K) anyway. /************************ END BM KLUDGE *****************************/ /* copy from the returned data buffer */ /* to our return parameter. */ memmove((void *)Buffer, (void *)readresBuffer(results), (size_t)(readresCount(results))); } xdr_free(xdr_readres, (char *)results); return(ReturnStatus); } /* RFSnfsRead */
/* Remote control server. */ void rc_listen (void) { char sockpath[128]; pid_t pid; struct sockaddr_un addr; int sock, s; size_t i; FILE *fp; XDR xdr, xdr2; guestfish_hello hello; guestfish_call call; guestfish_reply reply; char **argv; size_t argc; memset (&hello, 0, sizeof hello); memset (&call, 0, sizeof call); pid = fork (); if (pid == -1) { perror ("fork"); exit (EXIT_FAILURE); } if (pid > 0) { /* Parent process. */ if (!remote_control_csh) printf ("GUESTFISH_PID=%d; export GUESTFISH_PID\n", pid); else printf ("setenv GUESTFISH_PID %d\n", pid); fflush (stdout); _exit (0); } /* Child process. * * Create the listening socket for accepting commands. * * Unfortunately there is a small but unavoidable race here. We * don't know the PID until after we've forked, so we cannot be * sure the socket is created from the point of view of the parent * (if the child is very slow). */ pid = getpid (); create_sockpath (pid, sockpath, sizeof sockpath, &addr); sock = socket (AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); if (sock == -1) { perror ("socket"); exit (EXIT_FAILURE); } unlink (sockpath); if (bind (sock, (struct sockaddr *) &addr, sizeof addr) == -1) { perror (sockpath); exit (EXIT_FAILURE); } if (listen (sock, 4) == -1) { perror ("listen"); exit (EXIT_FAILURE); } /* Read commands and execute them. */ while (!quit) { /* Before waiting, close stdout and substitute /dev/null. This is * necessary so that eval `guestfish --listen` doesn't block * forever. */ close_stdout (); s = accept4 (sock, NULL, NULL, SOCK_CLOEXEC); if (s == -1) perror ("accept"); else { receive_stdout(s); fp = fdopen (s, "r+"); xdrstdio_create (&xdr, fp, XDR_DECODE); if (!xdr_guestfish_hello (&xdr, &hello)) { fprintf (stderr, _("guestfish: protocol error: could not read 'hello' message\n")); goto error; } if (STRNEQ (hello.vers, PACKAGE_VERSION)) { fprintf (stderr, _("guestfish: protocol error: version mismatch, server version '%s' does not match client version '%s'. The two versions must match exactly.\n"), PACKAGE_VERSION, hello.vers); xdr_free ((xdrproc_t) xdr_guestfish_hello, (char *) &hello); goto error; } xdr_free ((xdrproc_t) xdr_guestfish_hello, (char *) &hello); while (xdr_guestfish_call (&xdr, &call)) { /* We have to extend and NULL-terminate the argv array. */ argc = call.args.args_len; argv = realloc (call.args.args_val, (argc+1) * sizeof (char *)); if (argv == NULL) { perror ("realloc"); exit (EXIT_FAILURE); } call.args.args_val = argv; argv[argc] = NULL; if (verbose) { fprintf (stderr, "guestfish(%d): %s", pid, call.cmd); for (i = 0; i < argc; ++i) fprintf (stderr, " %s", argv[i]); fprintf (stderr, "\n"); } /* Run the command. */ reply.r = issue_command (call.cmd, argv, NULL, 0); xdr_free ((xdrproc_t) xdr_guestfish_call, (char *) &call); /* RHBZ#802389: If the command is quit, close the handle right * away. Note that the main while loop will exit preventing * 'g' from being reused. */ if (quit) { guestfs_close (g); g = NULL; } /* Send the reply. */ xdrstdio_create (&xdr2, fp, XDR_ENCODE); (void) xdr_guestfish_reply (&xdr2, &reply); xdr_destroy (&xdr2); /* Exit on error? */ if (call.exit_on_error && reply.r == -1) { unlink (sockpath); exit (EXIT_FAILURE); } } error: xdr_destroy (&xdr); /* NB. This doesn't close 'fp'. */ fclose (fp); /* Closes the underlying socket 's'. */ } } unlink (sockpath); close (sock); /* This returns to 'fish.c', where it jumps to global cleanups and exits. */ }
nis_result * nis_list (const_nis_name name, unsigned int flags, int (*callback) (const_nis_name name, const nis_object *object, const void *userdata), const void *userdata) { nis_result *res = malloc (sizeof (nis_result)); ib_request *ibreq; int status; enum clnt_stat clnt_status; int count_links = 0; /* We will only follow NIS_MAXLINKS links! */ int done = 0; nis_name *names; nis_name namebuf[2] = {NULL, NULL}; int name_nr = 0; nis_cb *cb = NULL; char *tableptr; char *tablepath = NULL; int first_try = 0; /* Do we try the old binding at first ? */ nis_result *allres = NULL; if (res == NULL) return NULL; if (name == NULL) { status = NIS_BADNAME; err_out: nis_freeresult (allres); memset (res, '\0', sizeof (nis_result)); NIS_RES_STATUS (res) = status; return res; } ibreq = __create_ib_request (name, flags); if (ibreq == NULL) { status = NIS_BADNAME; goto err_out; } if ((flags & EXPAND_NAME) && ibreq->ibr_name[strlen (ibreq->ibr_name) - 1] != '.') { names = nis_getnames (ibreq->ibr_name); free (ibreq->ibr_name); ibreq->ibr_name = NULL; if (names == NULL) { nis_free_request (ibreq); status = NIS_BADNAME; goto err_out; } ibreq->ibr_name = strdup (names[name_nr]); if (ibreq->ibr_name == NULL) { nis_freenames (names); nis_free_request (ibreq); status = NIS_NOMEMORY; goto err_out; } } else { names = namebuf; names[name_nr] = ibreq->ibr_name; } cb = NULL; while (!done) { dir_binding bptr; directory_obj *dir = NULL; memset (res, '\0', sizeof (nis_result)); status = __nisfind_server (ibreq->ibr_name, ibreq->ibr_srch.ibr_srch_val != NULL, &dir, &bptr, flags & ~MASTER_ONLY); if (status != NIS_SUCCESS) { NIS_RES_STATUS (res) = status; goto fail3; } while (__nisbind_connect (&bptr) != NIS_SUCCESS) if (__nisbind_next (&bptr) != NIS_SUCCESS) { NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE; goto fail; } if (callback != NULL) { assert (cb == NULL); cb = __nis_create_callback (callback, userdata, flags); ibreq->ibr_cbhost.ibr_cbhost_len = 1; ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv; } again: clnt_status = clnt_call (bptr.clnt, NIS_IBLIST, (xdrproc_t) _xdr_ib_request, (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result, (caddr_t) res, RPCTIMEOUT); if (clnt_status != RPC_SUCCESS) NIS_RES_STATUS (res) = NIS_RPCERROR; else switch (NIS_RES_STATUS (res)) { /* start switch */ case NIS_PARTIAL: case NIS_SUCCESS: case NIS_S_SUCCESS: if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ && (flags & FOLLOW_LINKS)) /* We are following links. */ { free (ibreq->ibr_name); ibreq->ibr_name = NULL; /* If we hit the link limit, bail. */ if (count_links > NIS_MAXLINKS) { NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; ++done; break; } ++count_links; ibreq->ibr_name = strdup (NIS_RES_OBJECT (res)->LI_data.li_name); if (ibreq->ibr_name == NULL) { NIS_RES_STATUS (res) = NIS_NOMEMORY; fail: __nisbind_destroy (&bptr); nis_free_directory (dir); fail3: free (tablepath); if (cb) { __nis_destroy_callback (cb); ibreq->ibr_cbhost.ibr_cbhost_len = 0; ibreq->ibr_cbhost.ibr_cbhost_val = NULL; } if (names != namebuf) nis_freenames (names); nis_free_request (ibreq); nis_freeresult (allres); return res; } if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len) if (ibreq->ibr_srch.ibr_srch_len == 0) { ibreq->ibr_srch.ibr_srch_len = NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len; ibreq->ibr_srch.ibr_srch_val = NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val; } /* The following is a non-obvious optimization. A nis_freeresult call would call xdr_free as the following code. But it also would unnecessarily free the result structure. We avoid this here along with the necessary tests. */ xdr_free ((xdrproc_t) _xdr_nis_result, (char *)res); memset (res, '\0', sizeof (*res)); first_try = 1; /* Try at first the old binding */ goto again; } else if ((flags & FOLLOW_PATH) && NIS_RES_STATUS (res) == NIS_PARTIAL) { enum nis_error err = __follow_path (&tablepath, &tableptr, ibreq, &bptr); if (err != NIS_SUCCESS) { if (err == NIS_NOMEMORY) NIS_RES_STATUS (res) = err; ++done; } else { /* The following is a non-obvious optimization. A nis_freeresult call would call xdr_free as the following code. But it also would unnecessarily free the result structure. We avoid this here along with the necessary tests. */ xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res); memset (res, '\0', sizeof (*res)); first_try = 1; goto again; } } else if ((flags & (FOLLOW_PATH | ALL_RESULTS)) == (FOLLOW_PATH | ALL_RESULTS)) { if (allres == NULL) { allres = res; res = malloc (sizeof (nis_result)); if (res == NULL) { res = allres; allres = NULL; NIS_RES_STATUS (res) = NIS_NOMEMORY; goto fail; } NIS_RES_STATUS (res) = NIS_RES_STATUS (allres); } else { nis_object *objects_val = realloc (NIS_RES_OBJECT (allres), (NIS_RES_NUMOBJ (allres) + NIS_RES_NUMOBJ (res)) * sizeof (nis_object)); if (objects_val == NULL) { NIS_RES_STATUS (res) = NIS_NOMEMORY; goto fail; } NIS_RES_OBJECT (allres) = objects_val; memcpy (NIS_RES_OBJECT (allres) + NIS_RES_NUMOBJ (allres), NIS_RES_OBJECT (res), NIS_RES_NUMOBJ (res) * sizeof (nis_object)); NIS_RES_NUMOBJ (allres) += NIS_RES_NUMOBJ (res); NIS_RES_NUMOBJ (res) = 0; free (NIS_RES_OBJECT (res)); NIS_RES_OBJECT (res) = NULL; NIS_RES_STATUS (allres) = NIS_RES_STATUS (res); xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res); } enum nis_error err = __follow_path (&tablepath, &tableptr, ibreq, &bptr); if (err != NIS_SUCCESS) { /* Prepare for the nis_freeresult call. */ memset (res, '\0', sizeof (*res)); if (err == NIS_NOMEMORY) NIS_RES_STATUS (allres) = err; ++done; } } else ++done; break; case NIS_CBRESULTS: if (cb != NULL) { __nis_do_callback (&bptr, &res->cookie, cb); NIS_RES_STATUS (res) = cb->result; if (!(flags & ALL_RESULTS)) ++done; else { enum nis_error err = __follow_path (&tablepath, &tableptr, ibreq, &bptr); if (err != NIS_SUCCESS) { if (err == NIS_NOMEMORY) NIS_RES_STATUS (res) = err; ++done; } } } break; case NIS_SYSTEMERROR: case NIS_NOSUCHNAME: case NIS_NOT_ME: /* If we had first tried the old binding, do nothing, but get a new binding */ if (!first_try) { if (__nisbind_next (&bptr) != NIS_SUCCESS) { ++done; break; /* No more servers to search */ } while (__nisbind_connect (&bptr) != NIS_SUCCESS) { if (__nisbind_next (&bptr) != NIS_SUCCESS) { ++done; break; /* No more servers to search */ } } goto again; } break; default: if (!first_try) { /* Try the next domainname if we don't follow a link. */ free (ibreq->ibr_name); ibreq->ibr_name = NULL; if (count_links) { NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; ++done; break; } ++name_nr; if (names[name_nr] == NULL) { ++done; break; } ibreq->ibr_name = strdup (names[name_nr]); if (ibreq->ibr_name == NULL) { NIS_RES_STATUS (res) = NIS_NOMEMORY; goto fail; } first_try = 1; /* Try old binding at first */ goto again; } break; } first_try = 0; if (cb) { __nis_destroy_callback (cb); ibreq->ibr_cbhost.ibr_cbhost_len = 0; ibreq->ibr_cbhost.ibr_cbhost_val = NULL; cb = NULL; } __nisbind_destroy (&bptr); nis_free_directory (dir); } free (tablepath); if (names != namebuf) nis_freenames (names); nis_free_request (ibreq); if (allres) { nis_freeresult (res); return allres; } return res; }
static int virNetClientProgramDispatchError(virNetClientProgramPtr prog ATTRIBUTE_UNUSED, virNetMessagePtr msg) { virNetMessageError err; int ret = -1; memset(&err, 0, sizeof(err)); if (virNetMessageDecodePayload(msg, (xdrproc_t)xdr_virNetMessageError, &err) < 0) goto cleanup; /* Interop for virErrorNumber glitch in 0.8.0, if server is * 0.7.1 through 0.7.7; see comments in virterror.h. */ switch (err.code) { case VIR_WAR_NO_NWFILTER: /* no way to tell old VIR_WAR_NO_SECRET apart from * VIR_WAR_NO_NWFILTER, but both are very similar * warnings, so ignore the difference */ break; case VIR_ERR_INVALID_NWFILTER: case VIR_ERR_NO_NWFILTER: case VIR_ERR_BUILD_FIREWALL: /* server was trying to pass VIR_ERR_INVALID_SECRET, * VIR_ERR_NO_SECRET, or VIR_ERR_CONFIG_UNSUPPORTED */ if (err.domain != VIR_FROM_NWFILTER) err.code += 4; break; case VIR_WAR_NO_SECRET: if (err.domain == VIR_FROM_QEMU) err.code = VIR_ERR_OPERATION_TIMEOUT; break; case VIR_ERR_INVALID_SECRET: if (err.domain == VIR_FROM_XEN) err.code = VIR_ERR_MIGRATE_PERSIST_FAILED; break; default: /* Nothing to alter. */ break; } if ((err.domain == VIR_FROM_REMOTE || err.domain == VIR_FROM_RPC) && err.code == VIR_ERR_RPC && err.level == VIR_ERR_ERROR && err.message && STRPREFIX(*err.message, "unknown procedure")) { virRaiseErrorFull(__FILE__, __FUNCTION__, __LINE__, err.domain, VIR_ERR_NO_SUPPORT, err.level, err.str1 ? *err.str1 : NULL, err.str2 ? *err.str2 : NULL, err.str3 ? *err.str3 : NULL, err.int1, err.int2, "%s", *err.message); } else { virRaiseErrorFull(__FILE__, __FUNCTION__, __LINE__, err.domain, err.code, err.level, err.str1 ? *err.str1 : NULL, err.str2 ? *err.str2 : NULL, err.str3 ? *err.str3 : NULL, err.int1, err.int2, "%s", err.message ? *err.message : _("Unknown error")); } ret = 0; cleanup: xdr_free((xdrproc_t)xdr_virNetMessageError, (void*)&err); return ret; }
guestfs_int_inotify_event_list * do_inotify_read (void) { #ifdef HAVE_SYS_INOTIFY_H int space; guestfs_int_inotify_event_list *ret; NEED_INOTIFY (NULL); ret = malloc (sizeof *ret); if (ret == NULL) { reply_with_perror ("malloc"); return NULL; } ret->guestfs_int_inotify_event_list_len = 0; ret->guestfs_int_inotify_event_list_val = NULL; /* Read events that are available, but make sure we won't exceed * maximum message size. In order to achieve this we have to * guesstimate the remaining space available. */ space = GUESTFS_MESSAGE_MAX / 2; while (space > 0) { struct inotify_event *event; int r; size_t n; r = read (inotify_fd, inotify_buf + inotify_posn, sizeof (inotify_buf) - inotify_posn); if (r == -1) { if (errno == EWOULDBLOCK || errno == EAGAIN) /* End of list. */ break; reply_with_perror ("read"); goto error; } if (r == 0) { /* End of file - we're not expecting it. */ reply_with_error ("unexpected end of file"); goto error; } inotify_posn += r; /* Read complete events from the buffer and add them to the result. */ n = 0; while (n < inotify_posn) { guestfs_int_inotify_event *np; guestfs_int_inotify_event *in; event = (struct inotify_event *) &inotify_buf[n]; /* Have we got a complete event in the buffer? */ #ifdef __GNUC__ if (n + sizeof (struct inotify_event) > inotify_posn || n + sizeof (struct inotify_event) + event->len > inotify_posn) break; #else #error "this code needs fixing so it works on non-GCC compilers" #endif np = realloc (ret->guestfs_int_inotify_event_list_val, (ret->guestfs_int_inotify_event_list_len + 1) * sizeof (guestfs_int_inotify_event)); if (np == NULL) { reply_with_perror ("realloc"); goto error; } ret->guestfs_int_inotify_event_list_val = np; in = &ret->guestfs_int_inotify_event_list_val[ret->guestfs_int_inotify_event_list_len]; ret->guestfs_int_inotify_event_list_len++; in->in_wd = event->wd; in->in_mask = event->mask; in->in_cookie = event->cookie; if (event->len > 0) in->in_name = strdup (event->name); else in->in_name = strdup (""); /* Should have optional string fields XXX. */ if (in->in_name == NULL) { reply_with_perror ("strdup"); goto error; } /* Estimate space used by this event in the message. */ space -= 16 + 4 + strlen (in->in_name) + 4; /* Move pointer to next event. */ #ifdef __GNUC__ n += sizeof (struct inotify_event) + event->len; #else #error "this code needs fixing so it works on non-GCC compilers" #endif } /* 'n' now points to the first unprocessed/incomplete * message in the buffer. Copy that to offset 0 in the buffer. */ memmove (inotify_buf, &inotify_buf[n], inotify_posn - n); inotify_posn -= n; } /* Return the messages. */ return ret; error: xdr_free ((xdrproc_t) xdr_guestfs_int_inotify_event_list, (char *) ret); free (ret); return NULL; #else NOT_AVAILABLE (NULL); #endif }
/* Receive file chunks, repeatedly calling 'cb'. */ int receive_file (receive_cb cb, void *opaque) { guestfs_chunk chunk; char lenbuf[4]; XDR xdr; int r; uint32_t len; for (;;) { CLEANUP_FREE char *buf = NULL; if (verbose) fprintf (stderr, "guestfsd: receive_file: reading length word\n"); /* Read the length word. */ if (xread (sock, lenbuf, 4) == -1) exit (EXIT_FAILURE); xdrmem_create (&xdr, lenbuf, 4, XDR_DECODE); xdr_u_int (&xdr, &len); xdr_destroy (&xdr); if (len == GUESTFS_CANCEL_FLAG) continue; /* Just ignore it. */ if (len > GUESTFS_MESSAGE_MAX) error (EXIT_FAILURE, 0, "incoming message is too long (%u bytes)", len); buf = malloc (len); if (!buf) { perror ("malloc"); return -1; } if (xread (sock, buf, len) == -1) exit (EXIT_FAILURE); xdrmem_create (&xdr, buf, len, XDR_DECODE); memset (&chunk, 0, sizeof chunk); if (!xdr_guestfs_chunk (&xdr, &chunk)) { xdr_destroy (&xdr); return -1; } xdr_destroy (&xdr); if (verbose) fprintf (stderr, "guestfsd: receive_file: got chunk: cancel = 0x%x, len = %u, buf = %p\n", (unsigned) chunk.cancel, chunk.data.data_len, chunk.data.data_val); if (chunk.cancel != 0 && chunk.cancel != 1) { fprintf (stderr, "guestfsd: receive_file: chunk.cancel != [0|1] ... " "continuing even though we have probably lost synchronization with the library\n"); return -1; } if (chunk.cancel) { if (verbose) fprintf (stderr, "guestfsd: receive_file: received cancellation from library\n"); xdr_free ((xdrproc_t) xdr_guestfs_chunk, (char *) &chunk); return -2; } if (chunk.data.data_len == 0) { if (verbose) fprintf (stderr, "guestfsd: receive_file: end of file, leaving function\n"); xdr_free ((xdrproc_t) xdr_guestfs_chunk, (char *) &chunk); return 0; /* end of file */ } /* Note that the callback can generate progress messages. */ if (cb) r = cb (opaque, chunk.data.data_val, chunk.data.data_len); else r = 0; xdr_free ((xdrproc_t) xdr_guestfs_chunk, (char *) &chunk); if (r == -1) { /* write error */ if (verbose) fprintf (stderr, "guestfsd: receive_file: write error\n"); return -1; } } }
static bool_t xdr_ypxfr_xfr (XDR *xdrs, xfr *objp) { while (1) { if (!xdr_xfr (xdrs, objp)) return (FALSE); if (objp->ok == TRUE) { if (write (ypxfrd_file, objp->xfr_u.xfrblock_buf.xfrblock_buf_val, objp->xfr_u.xfrblock_buf.xfrblock_buf_len) == -1) { log_msg ("write failed: %s", strerror (errno)); return FALSE; } } xdr_free ((xdrproc_t) xdr_xfr, (char *) objp); if (objp->ok == FALSE) { switch (objp->xfr_u.xfrstat) { case XFR_DONE: return TRUE; break; case XFR_DENIED: log_msg ("access to map denied by rpc.ypxfrd"); return FALSE; break; case XFR_NOFILE: log_msg ("reqested map does not exist"); return FALSE; break; case XFR_ACCESS: log_msg ("rpc.ypxfrd couldn't access the map"); return FALSE; break; case XFR_BADDB: log_msg ("file is not a database"); return FALSE; break; case XFR_READ_OK: if (debug_flag) log_msg ("block read successfully"); return TRUE; break; case XFR_READ_ERR: log_msg ("got read error from rpc.ypxfrd"); return FALSE; break; case XFR_DB_ENDIAN_MISMATCH: log_msg ("rpc.ypxfrd databases have the wrong endian"); return FALSE; break; case XFR_DB_TYPE_MISMATCH: log_msg ("rpc.ypxfrd doesn't support the needed database type"); return FALSE; break; default: log_msg ("got unknown status from rpc.ypxfrd"); return FALSE; break; } } } }
static int nfs3mountroot(char *path, struct nfs_file *filep) { int rexmit; int resp_wait; struct mountres3 res3; enum clnt_stat status; /* * Wait up to 16 secs for first response, retransmitting expon. */ rexmit = 0; /* default retransmission interval */ resp_wait = 16; /* * Try to mount using V3 */ do { bzero(&res3, sizeof (struct mountres3)); status = brpc_call((rpcprog_t)MOUNTPROG, (rpcvers_t)MOUNTVERS3, (rpcproc_t)MOUNTPROC_MNT, xdr_path, (caddr_t)&path, xdr_mountres3, (caddr_t)&res3, rexmit, resp_wait, &root_to, NULL, AUTH_UNIX); if (status != RPC_TIMEDOUT) break; dprintf("boot: %s:%s mount server not responding.\n", root_hostname, path); rexmit = resp_wait; resp_wait = 0; /* use default wait time. */ xdr_free(xdr_mountres3, (caddr_t)&res3); } while (status == RPC_TIMEDOUT); if ((status != RPC_SUCCESS) || (res3.fhs_status != MNT_OK)) { mnt3_error(res3.fhs_status); root_to.sin_port = 0; return (-1); } /* * Since the mount succeeded, we'll mark the filep's * status as NFS_OK, and its type as NF3DIR. If these * points aren't the case, then we wouldn't be here. */ filep->fh.fh3.len = res3.mountres3_u.mountinfo.fhandle.fhandle3_len; bcopy(res3.mountres3_u.mountinfo.fhandle.fhandle3_val, filep->fh.fh3.data, filep->fh.fh3.len); filep->ftype.type3 = NF3DIR; filep->version = NFS_V3; /* * Hardwire in a known reasonable upper limit of 32K */ nfs_readsize = nfs_readsize < 32 * 1024 ? nfs_readsize : 32 * 1024; /* * Set a reasonable lower limit on readsize */ nfs_readsize = (nfs_readsize != 0 && nfs_readsize < 512) ? 512 : nfs_readsize; xdr_free(xdr_mountres3, (caddr_t)&res3); return (0); }
/* * Input: Pointer to an XDR:ed version of an (xdr_nis_object_t). * Output: Pointer to a (nis_object *) and (if the object is a * directory) a pointer to an array of (entry_obj *). */ nis_object * unXdrNisObject(void *buf, int bufLen, entry_obj ***eaP, int *numEaP) { xdr_nis_object_t *xno; XDR xdrs; bool_t xret; entry_obj **ea; int numEa; nis_object *o; char *myself = "unXdrNisObject"; if (buf == 0 || bufLen <= 0) return (0); xno = am(myself, sizeof (*xno)); if (xno == 0) return (0); xdrmem_create(&xdrs, buf, bufLen, XDR_DECODE); xret = xdr_xdr_nis_object_t(&xdrs, xno); if (!xret) { sfree(xno); return (0); } switch (xno->xversion) { case 1: break; default: xdr_free(xdr_xdr_nis_object_t, (char *)xno); sfree(xno); logmsg(MSG_NOTIMECHECK, LOG_WARNING, "%s: Unknown xdr_nis_object_t version %d", myself, xno->xversion); return (0); } if (eaP != 0 && numEaP != 0 && xno->dirEntry.dirEntry_len > 0 && xno->dirEntry.dirEntry_val != 0) { ea = am(myself, xno->dirEntry.dirEntry_len * sizeof (ea[0])); if (ea == 0) { xdr_free(xdr_xdr_nis_object_t, (char *)xno); sfree(xno); return (0); } for (numEa = 0; numEa < xno->dirEntry.dirEntry_len; numEa++) { ea[numEa] = am(myself, sizeof (*ea[numEa])); if (ea[numEa] != 0) { ea[numEa]->en_cols.en_cols_len = 2; ea[numEa]->en_cols.en_cols_val = am(myself, ea[numEa]->en_cols.en_cols_len * sizeof (ea[numEa]->en_cols.en_cols_val[0])); } if (ea[numEa] == 0 || ea[numEa]->en_cols.en_cols_val == 0) { int i; for (i = 0; i < numEa; i++) { sfree(ea[i]->en_cols.en_cols_val); sfree(ea[i]); } sfree(ea); xdr_free(xdr_xdr_nis_object_t, (char *)xno); sfree(xno); return (0); } /* Leave column 0 (XDR:ed object) empty */ ea[numEa]->en_cols.en_cols_val[0]. ec_value.ec_value_len = 0; ea[numEa]->en_cols.en_cols_val[0]. ec_value.ec_value_val = 0; /* * Fill in name of dir entry. The DB counts the NUL * as part of the dir entry name; hence, add one * to the string length. */ ea[numEa]->en_cols.en_cols_val[1]. ec_value.ec_value_len = slen(xno->dirEntry. dirEntry_val[numEa]) + 1; ea[numEa]->en_cols.en_cols_val[1]. ec_value.ec_value_val = xno->dirEntry.dirEntry_val[numEa]; } *eaP = ea; *numEaP = numEa; /* * The xno->dirEntry.dirEntry_val[] pointers are duplicated * in 'ea'. Set the xno pointers to zero, so that the xdr_free * doesn't free the 'ea' data. */ if (numEa > 0) { int i; for (i = 0; i < numEa; i++) { xno->dirEntry.dirEntry_val[i] = 0; } } } else { if (eaP != 0) *eaP = 0; if (numEaP != 0) *numEaP = 0; } o = xno->obj; xno->obj = 0; xdr_free(xdr_xdr_nis_object_t, (char *)xno); sfree(xno); return (o); }
enum clnt_stat rpcbind_getaddr(struct knetconfig *config, rpcprog_t prog, rpcvers_t vers, struct netbuf *addr) { char *ua = NULL; enum clnt_stat status; RPCB parms; struct timeval tmo; CLIENT *client = NULL; k_sigset_t oldmask; k_sigset_t newmask; ushort_t port; int iptype; /* * Call rpcbind (local or remote) to get an address we can use * in an RPC client handle. */ tmo.tv_sec = RPC_PMAP_TIMEOUT; tmo.tv_usec = 0; parms.r_prog = prog; parms.r_vers = vers; parms.r_addr = parms.r_owner = ""; if (strcmp(config->knc_protofmly, NC_INET) == 0) { if (strcmp(config->knc_proto, NC_TCP) == 0) parms.r_netid = "tcp"; else parms.r_netid = "udp"; put_inet_port(addr, htons(PMAPPORT)); } else if (strcmp(config->knc_protofmly, NC_INET6) == 0) { if (strcmp(config->knc_proto, NC_TCP) == 0) parms.r_netid = "tcp6"; else parms.r_netid = "udp6"; put_inet6_port(addr, htons(PMAPPORT)); } else if (strcmp(config->knc_protofmly, NC_LOOPBACK) == 0) { ASSERT(strnrchr(addr->buf, '.', addr->len) != NULL); if (config->knc_semantics == NC_TPI_COTS_ORD) parms.r_netid = "ticotsord"; else if (config->knc_semantics == NC_TPI_COTS) parms.r_netid = "ticots"; else parms.r_netid = "ticlts"; put_loopback_port(addr, "rpc"); } else { status = RPC_UNKNOWNPROTO; goto out; } /* * Mask signals for the duration of the handle creation and * RPC calls. This allows relatively normal operation with a * signal already posted to our thread (e.g., when we are * sending an NLM_CANCEL in response to catching a signal). * * Any further exit paths from this routine must restore * the original signal mask. */ sigfillset(&newmask); sigreplace(&newmask, &oldmask); if (clnt_tli_kcreate(config, addr, RPCBPROG, RPCBVERS, 0, 0, CRED(), &client)) { status = RPC_TLIERROR; sigreplace(&oldmask, (k_sigset_t *)NULL); goto out; } client->cl_nosignal = 1; if ((status = CLNT_CALL(client, RPCBPROC_GETADDR, xdr_rpcb, (char *)&parms, xdr_wrapstring, (char *)&ua, tmo)) != RPC_SUCCESS) { sigreplace(&oldmask, (k_sigset_t *)NULL); goto out; } sigreplace(&oldmask, (k_sigset_t *)NULL); if (ua == NULL || *ua == NULL) { status = RPC_PROGNOTREGISTERED; goto out; } /* * Convert the universal address to the transport address. * Theoretically, we should call the local rpcbind to translate * from the universal address to the transport address, but it gets * complicated (e.g., there's no direct way to tell rpcbind that we * want an IP address instead of a loopback address). Note that * the transport address is potentially host-specific, so we can't * just ask the remote rpcbind, because it might give us the wrong * answer. */ if (strcmp(config->knc_protofmly, NC_INET) == 0) { /* make sure that the ip address is the correct type */ if (rpc_iptype(ua, &iptype) != 0) { status = RPC_UNKNOWNADDR; goto out; } port = rpc_uaddr2port(iptype, ua); put_inet_port(addr, ntohs(port)); } else if (strcmp(config->knc_protofmly, NC_INET6) == 0) { /* make sure that the ip address is the correct type */ if (rpc_iptype(ua, &iptype) != 0) { status = RPC_UNKNOWNADDR; goto out; } port = rpc_uaddr2port(iptype, ua); put_inet6_port(addr, ntohs(port)); } else if (strcmp(config->knc_protofmly, NC_LOOPBACK) == 0) { loopb_u2t(ua, addr); } else { /* "can't happen" - should have been checked for above */ cmn_err(CE_PANIC, "rpcbind_getaddr: bad protocol family"); } out: if (client != NULL) { auth_destroy(client->cl_auth); clnt_destroy(client); } if (ua != NULL) xdr_free(xdr_wrapstring, (char *)&ua); return (status); }
int rdictprog_1_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result) { xdr_free (xdr_result, result); return 1; }
OM_uint32 gpm_init_sec_context(OM_uint32 *minor_status, gssx_cred *cred_handle, gssx_ctx **context_handle, gssx_name *target_name, gss_OID mech_type, OM_uint32 req_flags, OM_uint32 time_req, gss_channel_bindings_t input_cb, gss_buffer_t input_token, gss_OID *actual_mech_type, gss_buffer_t output_token, OM_uint32 *ret_flags, OM_uint32 *time_rec) { union gp_rpc_arg uarg; union gp_rpc_res ures; gssx_arg_init_sec_context *arg = &uarg.init_sec_context; gssx_res_init_sec_context *res = &ures.init_sec_context; gssx_ctx *ctx = NULL; gss_OID_desc *mech = NULL; gss_buffer_t outbuf = NULL; uint32_t ret_maj = GSS_S_COMPLETE; uint32_t ret_min = 0; int ret; memset(&uarg, 0, sizeof(union gp_rpc_arg)); memset(&ures, 0, sizeof(union gp_rpc_res)); /* prepare proxy request */ if (cred_handle != NULL) { arg->cred_handle = cred_handle; } if (*context_handle) { arg->context_handle = *context_handle; } arg->target_name = target_name; ret = gp_conv_oid_to_gssx(mech_type, &arg->mech_type); if (ret) { goto done; } arg->req_flags = req_flags; arg->time_req = time_req; if (input_cb) { ret = gp_conv_cb_to_gssx_alloc(input_cb, &arg->input_cb); if (ret) { goto done; } } if (input_token != GSS_C_NO_BUFFER) { ret = gp_conv_buffer_to_gssx_alloc(input_token, &arg->input_token); if (ret) { goto done; } } /* execute proxy request */ ret = gpm_make_call(GSSX_INIT_SEC_CONTEXT, &uarg, &ures); if (ret) { gpm_save_internal_status(ret, gp_strerror(ret)); goto done; } /* return values */ if (actual_mech_type) { if (res->status.mech.octet_string_len) { ret = gp_conv_gssx_to_oid_alloc(&res->status.mech, &mech); if (ret) { goto done; } } } if (res->context_handle) { ctx = res->context_handle; /* we are stealing the delegated creds on success, so we do not want * it to be freed by xdr_free */ res->context_handle = NULL; } if (res->output_token) { ret = gp_conv_gssx_to_buffer_alloc(res->output_token, &outbuf); if (ret) { gpm_save_internal_status(ret, gp_strerror(ret)); goto done; } } ret_maj = res->status.major_status; ret_min = res->status.minor_status; gpm_save_status(&res->status); done: if (ret != 0) { ret_min = ret; ret_maj = GSS_S_FAILURE; } /* we are putting our copy of these structures in here, * and do not want it to be freed by xdr_free */ arg->context_handle = NULL; arg->cred_handle = NULL; arg->target_name = NULL; gpm_free_xdrs(GSSX_INIT_SEC_CONTEXT, &uarg, &ures); if (ret_maj == GSS_S_COMPLETE || ret_maj == GSS_S_CONTINUE_NEEDED) { /* replace old ctx handle if any */ if (*context_handle) { xdr_free((xdrproc_t)xdr_gssx_ctx, (char *)*context_handle); free(*context_handle); } *context_handle = ctx; if (actual_mech_type) { *actual_mech_type = mech; } if (outbuf) { *output_token = *outbuf; free(outbuf); } if (ret_flags) { *ret_flags = ctx->ctx_flags; } if (time_rec) { *time_rec = ctx->lifetime; } } else { if (ctx) { xdr_free((xdrproc_t)xdr_gssx_ctx, (char *)ctx); free(ctx); } if (mech) { free(mech->elements); free(mech); } if (outbuf) { free(outbuf->value); free(outbuf); } } *minor_status = ret_min; return ret_maj; }
OM_uint32 gppint_get_def_creds(OM_uint32 *minor_status, enum gpp_behavior behavior, struct gpp_name_handle *name, gss_cred_usage_t cred_usage, struct gpp_cred_handle **cred_handle) { struct gpp_cred_handle *cred; OM_uint32 tmaj = GSS_S_COMPLETE; OM_uint32 tmin = 0; OM_uint32 maj = GSS_S_FAILURE; OM_uint32 min = 0; cred = calloc(1, sizeof(struct gpp_cred_handle)); if (!cred) { min = ENOMEM; goto done; } /* See if we should try local first */ if (behavior == GPP_LOCAL_ONLY || behavior == GPP_LOCAL_FIRST) { maj = get_local_def_creds(&min, name, cred_usage, cred); if (maj != GSS_S_NO_CRED || behavior != GPP_LOCAL_FIRST) { goto done; } /* not successful, save actual local error if remote fallback fails */ tmaj = maj; tmin = min; } /* Then try with remote */ if (behavior == GPP_REMOTE_ONLY || behavior == GPP_REMOTE_FIRST) { gssx_cred remote; gssx_cred *premote = NULL; memset(&remote, 0, sizeof(gssx_cred)); /* We intentionally ignore failures as finding creds is optional */ maj = retrieve_remote_creds(&min, name ? name->remote : NULL, &remote); if (maj == GSS_S_COMPLETE) { premote = &remote; } maj = gpm_acquire_cred(&min, premote, NULL, 0, NULL, cred_usage, false, &cred->remote, NULL, NULL); xdr_free((xdrproc_t)xdr_gssx_cred, (char *)&remote); if (maj == GSS_S_COMPLETE || behavior == GPP_REMOTE_ONLY) { goto done; } /* So remote failed, but we can fallback to local, try that */ maj = get_local_def_creds(&min, name, cred_usage, cred); } done: if (maj != GSS_S_COMPLETE && tmaj != GSS_S_COMPLETE) { maj = tmaj; min = tmin; } *minor_status = min; if (maj != GSS_S_COMPLETE) { gssi_release_cred(&min, (gss_cred_id_t *)&cred); } *cred_handle = cred; return maj; }
int gpm_make_call(int proc, union gp_rpc_arg *arg, union gp_rpc_res *res) { struct gpm_ctx *gpmctx; gp_rpc_msg msg; XDR xdr_call_ctx; XDR xdr_reply_ctx; char buffer[MAX_RPC_SIZE]; uint32_t length; uint32_t xid; bool xdrok; bool sockgrab = false; int ret; xdrmem_create(&xdr_call_ctx, buffer, MAX_RPC_SIZE, XDR_ENCODE); xdrmem_create(&xdr_reply_ctx, buffer, MAX_RPC_SIZE, XDR_DECODE); memset(&msg, 0, sizeof(gp_rpc_msg)); msg.header.type = GP_RPC_CALL; msg.header.gp_rpc_msg_union_u.chdr.rpcvers = 2; msg.header.gp_rpc_msg_union_u.chdr.prog = GSSPROXY; msg.header.gp_rpc_msg_union_u.chdr.vers = GSSPROXYVERS; msg.header.gp_rpc_msg_union_u.chdr.proc = proc; msg.header.gp_rpc_msg_union_u.chdr.cred.flavor = GP_RPC_AUTH_NONE; msg.header.gp_rpc_msg_union_u.chdr.cred.body.body_len = 0; msg.header.gp_rpc_msg_union_u.chdr.cred.body.body_val = NULL; msg.header.gp_rpc_msg_union_u.chdr.verf.flavor = GP_RPC_AUTH_NONE; msg.header.gp_rpc_msg_union_u.chdr.verf.body.body_len = 0; msg.header.gp_rpc_msg_union_u.chdr.verf.body.body_val = NULL; gpmctx = gpm_get_ctx(); if (!gpmctx) { return EINVAL; } /* grab the lock for the whole conversation */ ret = gpm_grab_sock(gpmctx); if (ret) { goto done; } sockgrab = true; msg.xid = xid = gpm_next_xid(gpmctx); /* encode header */ xdrok = xdr_gp_rpc_msg(&xdr_call_ctx, &msg); if (!xdrok) { ret = EINVAL; goto done; } /* encode data */ xdrok = gpm_xdr_set[proc].arg_fn(&xdr_call_ctx, (char *)arg); if (!xdrok) { ret = EINVAL; goto done; } /* send to proxy */ ret = gpm_send_buffer(gpmctx, buffer, xdr_getpos(&xdr_call_ctx)); if (ret) { goto done; } /* receive answer */ ret = gpm_recv_buffer(gpmctx, buffer, &length); if (ret) { goto done; } /* release the lock */ gpm_release_sock(gpmctx); sockgrab = false; /* decode header */ memset(&msg, 0, sizeof(gp_rpc_msg)); xdrok = xdr_gp_rpc_msg(&xdr_reply_ctx, &msg); if (!xdrok) { ret = EINVAL; goto done; } if (msg.xid != xid || msg.header.type != GP_RPC_REPLY || msg.header.gp_rpc_msg_union_u.rhdr.status != GP_RPC_MSG_ACCEPTED || msg.header.gp_rpc_msg_union_u.rhdr.gp_rpc_reply_header_u.accepted.reply_data.status != GP_RPC_SUCCESS) { ret = EINVAL; goto done; } /* decode answer */ xdrok = gpm_xdr_set[proc].res_fn(&xdr_reply_ctx, (char *)res); if (!xdrok) { ret = EINVAL; } done: if (sockgrab) { gpm_release_sock(gpmctx); } xdr_free((xdrproc_t)xdr_gp_rpc_msg, (char *)&msg); xdr_destroy(&xdr_call_ctx); xdr_destroy(&xdr_reply_ctx); gpm_release_ctx(gpmctx); return ret; }