static int get_peercred(int fd, struct gp_conn *conn) { SEC_CTX secctx; socklen_t len; int ret; len = sizeof(struct ucred); ret = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &conn->creds.ucred, &len); if (ret == -1) { ret = errno; GPDEBUG("Failed to get SO_PEERCRED options! (%d:%s)\n", ret, gp_strerror(ret)); return ret; } if (len != sizeof(struct ucred)) { return EIO; } conn->creds.type |= CRED_TYPE_UNIX; ret = SELINUX_getpeercon(fd, &secctx); if (ret == 0) { conn->creds.type |= CRED_TYPE_SELINUX; conn->selinux_ctx = SELINUX_context_new(secctx); SELINUX_freecon(secctx); } else { ret = errno; GPDEBUG("Failed to get peer's SELinux context (%d:%s)\n", ret, gp_strerror(ret)); /* consider thisnot fatal, selinux may be disabled */ } return 0; }
/* <int> .oserrorstring false */ static int zoserrorstring(i_ctx_t *i_ctx_p) { os_ptr op = osp; const char *str; int code; uint len; byte ch; check_type(*op, t_integer); str = gp_strerror((int)op->value.intval); if (str == 0 || (len = strlen(str)) == 0) { make_false(op); return 0; } check_ostack(1); code = string_to_ref(str, op, iimemory, ".oserrorstring"); if (code < 0) return code; /* Strip trailing end-of-line characters. */ while ((len = r_size(op)) != 0 && ((ch = op->value.bytes[--len]) == '\r' || ch == '\n') ) r_dec_size(op, 1); push(1); make_true(op); return 0; }
static int gp_config_from_file(const char *config_file, struct gp_ini_context *ctx, struct ini_cfgobj *ini_config, const uint32_t collision_flags) { struct ini_cfgfile *file_ctx = NULL; int ret; ret = ini_config_file_open(config_file, 0, /* metadata_flags, FIXME */ &file_ctx); if (ret) { GPDEBUG("Failed to open config file: %d (%s)\n", ret, gp_strerror(ret)); ini_config_destroy(ini_config); return ret; } ret = ini_config_parse(file_ctx, INI_STOP_ON_ANY, /* error_level */ collision_flags, INI_PARSE_NOWRAP, /* parse_flags */ ini_config); if (ret) { char **errors = NULL; /* we had a parsing failure */ GPDEBUG("Failed to parse config file: %d (%s)\n", ret, gp_strerror(ret)); if (ini_config_error_count(ini_config)) { ini_config_get_errors(ini_config, &errors); if (errors) { ini_config_print_errors(stderr, errors); ini_config_free_errors(errors); } } ini_config_file_destroy(file_ctx); ini_config_destroy(ini_config); return ret; } ini_config_file_destroy(file_ctx); return 0; }
int load_config(struct gp_config *cfg) { struct gp_ini_context *ctx; const char *tmpstr; int tmpint = 0; int ret; ret = gp_init_ini_context(cfg->config_file, cfg->config_dir, &ctx); if (ret) { return ret; } ret = gp_config_get_string(ctx, "gssproxy", "debug", &tmpstr); if (ret == 0) { if (gp_boolean_is_true(tmpstr)) { gp_debug_enable(1); } } else if (ret != ENOENT) { goto done; } ret = gp_config_get_int(ctx, "gssproxy", "debug_level", &tmpint); if (ret == 0) { gp_debug_enable(tmpint); } else if (ret != ENOENT) { goto done; } ret = gp_config_get_string(ctx, "gssproxy", "run_as_user", &tmpstr); if (ret == 0) { cfg->proxy_user = strdup(tmpstr); if (!cfg->proxy_user) { ret = ENOMEM; goto done; } } else if (ret != ENOENT) { goto done; } ret = gp_config_get_int(ctx, "gssproxy", "worker threads", &cfg->num_workers); if (ret != 0 && ret != ENOENT) { goto done; } ret = load_services(cfg, ctx); done: if (ret != 0) { GPERROR("Error reading configuration %d: %s", ret, gp_strerror(ret)); } gp_config_close(ctx); safefree(ctx); return ret; }
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; }
void accept_sock_conn(verto_ctx *vctx, verto_ev *ev) { struct gp_conn *conn = NULL; int listen_fd; int fd = -1; int ret; conn = calloc(1, sizeof(struct gp_conn)); if (!conn) { ret = ENOMEM; goto done; } conn->sock_ctx = verto_get_private(ev); conn->us.sd = -1; listen_fd = verto_get_fd(ev); fd = accept(listen_fd, (struct sockaddr *)&conn->us.sock_addr, &conn->us.sock_addr_len); if (fd == -1) { ret = errno; if (ret == EINTR) { /* let the event loop retry later */ return; } goto done; } conn->us.sd = fd; ret = set_status_flags(fd, O_NONBLOCK); if (ret) { GPDEBUG("Failed to set O_NONBLOCK on %d!\n", fd); goto done; } ret = set_fd_flags(fd, FD_CLOEXEC); if (ret) { GPDEBUG("Failed to set FD_CLOEXEC on %d!\n", fd); goto done; } ret = get_peercred(fd, conn); if (ret) { goto done; } GPDEBUG("Client connected (fd = %d)", fd); if (conn->creds.type & CRED_TYPE_UNIX) { GPDEBUG(" (pid = %d) (uid = %d) (gid = %d)", conn->creds.ucred.pid, conn->creds.ucred.uid, conn->creds.ucred.gid); } if (conn->creds.type & CRED_TYPE_SELINUX) { GPDEBUG(" (context = %s)", SELINUX_context_str(conn->selinux_ctx)); } GPDEBUG("\n"); gp_setup_reader(vctx, conn); ret = 0; done: if (ret) { GPERROR("Error connecting client: (%d:%s)", ret, gp_strerror(ret)); gp_conn_free(conn); } }
struct gp_sock_ctx *init_unix_socket(struct gssproxy_ctx *gpctx, const char *file_name) { struct sockaddr_un addr = {0}; struct gp_sock_ctx *sock_ctx; mode_t old_mode; int ret = 0; int fd = -1; sock_ctx = calloc(1, sizeof(struct gp_sock_ctx)); if (!sock_ctx) { return NULL; } /* can't bind if an old socket is around */ unlink(file_name); /* socket should be r/w by anyone */ old_mode = umask(0111); addr.sun_family = AF_UNIX; strncpy(addr.sun_path, file_name, sizeof(addr.sun_path)-1); addr.sun_path[sizeof(addr.sun_path)-1] = '\0'; fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) { ret = errno; GPDEBUG("Failed to init socket! (%d: %s)\n", ret, gp_strerror(ret)); goto done; } ret = bind(fd, (struct sockaddr *)&addr, sizeof(addr)); if (ret == -1) { ret = errno; GPDEBUG("Failed to bind socket %s! (%d: %s)\n", addr.sun_path, ret, gp_strerror(ret)); goto done; } ret = listen(fd, 10); if (ret == -1) { ret = errno; GPDEBUG("Failed to listen! (%d: %s)\n", ret, gp_strerror(ret)); goto done; } ret = set_status_flags(fd, O_NONBLOCK); if (ret != 0) { GPDEBUG("Failed to set O_NONBLOCK on %d!\n", fd); goto done; } ret = set_fd_flags(fd, FD_CLOEXEC); if (ret != 0) { GPDEBUG("Failed to set FD_CLOEXEC on %d!\n", fd); goto done; } done: if (ret) { GPERROR("Failed to create Unix Socket! (%d:%s)", ret, gp_strerror(ret)); if (fd != -1) { close(fd); fd = -1; } safefree(sock_ctx); } else { sock_ctx->gpctx = gpctx; sock_ctx->socket = file_name; sock_ctx->fd = fd; } umask(old_mode); return sock_ctx; }