コード例 #1
0
ファイル: gp_socket.c プロジェクト: frozencemetery/gssproxy
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;
}
コード例 #2
0
ファイル: zmisc.c プロジェクト: hackqiang/gs
/* <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;
}
コード例 #3
0
ファイル: gp_config.c プロジェクト: frozencemetery/gssproxy
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;
}
コード例 #4
0
ファイル: gp_config.c プロジェクト: frozencemetery/gssproxy
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;
}
コード例 #5
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;
}
コード例 #6
0
ファイル: gp_socket.c プロジェクト: frozencemetery/gssproxy
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);
    }
}
コード例 #7
0
ファイル: gp_socket.c プロジェクト: frozencemetery/gssproxy
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;
}