Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
/*
 * @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;
}
Ejemplo n.º 3
0
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);
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
/*ARGSUSED*/
bool_t
metad_2_freeresult(SVCXPRT *unused, xdrproc_t xdr_result, caddr_t result)
{
	xdr_free(xdr_result, result);
	return (TRUE);
}
Ejemplo n.º 6
0
//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;
}
Ejemplo n.º 7
0
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;
}
Ejemplo n.º 8
0
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;
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
/* 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;
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
0
/**
  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);
}
Ejemplo n.º 13
0
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;
}
Ejemplo n.º 15
0
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 */
Ejemplo n.º 16
0
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;
}
Ejemplo n.º 17
0
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 */
Ejemplo n.º 18
0
/* 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. */
}
Ejemplo n.º 19
0
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;
}
Ejemplo n.º 20
0
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;
}
Ejemplo n.º 21
0
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
}
Ejemplo n.º 22
0
/* 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;
    }
  }
}
Ejemplo n.º 23
0
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;
            }
        }
    }
}
Ejemplo n.º 24
0
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);
}
Ejemplo n.º 25
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);
}
Ejemplo n.º 26
0
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);
}
Ejemplo n.º 27
0
int rdictprog_1_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
{
	xdr_free (xdr_result, result);

	return 1;
}
Ejemplo n.º 28
0
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;
}
Ejemplo n.º 29
0
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;
}
Ejemplo n.º 30
0
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;
}