Beispiel #1
0
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;
}
Beispiel #2
0
static void gp_set_cred_options(gssx_cred *cred, gss_cred_id_t gss_cred)
{
    struct gssx_cred_element *ce;
    struct gssx_option *op;
    uint32_t num_ktypes = 0;
    krb5_enctype *ktypes;
    uint32_t maj, min;
    int i, j;

    for (i = 0; i < cred->elements.elements_len; i++) {
        ce = &cred->elements.elements_val[i];
        for (j = 0; j < ce->options.options_len; j++) {
            op = &ce->options.options_val[j];
            if ((op->option.octet_string_len ==
                    sizeof(KRB5_SET_ALLOWED_ENCTYPE)) &&
                (strncmp(KRB5_SET_ALLOWED_ENCTYPE,
                         op->option.octet_string_val,
                         op->option.octet_string_len) == 0)) {
                num_ktypes = op->value.octet_string_len / sizeof(krb5_enctype);
                ktypes = (krb5_enctype *)op->value.octet_string_val;
                break;
            }
        }
    }

    if (num_ktypes) {
        maj = gss_krb5_set_allowable_enctypes(&min, gss_cred,
                                              num_ktypes, ktypes);
        if (maj != GSS_S_COMPLETE) {
            GPDEBUG("Failed to set allowable enctypes\n");
        }
    }
}
static int gp_rpc_execute(struct gp_call_ctx *gpcall, uint32_t proc,
                          union gp_rpc_arg *arg, union gp_rpc_res *res)
{
    GPDEBUG("gp_rpc_execute: executing %d (%s) for service \"%s\", euid: %d, socket: %s\n",
        proc, gp_rpc_procname(proc), gpcall->service->name,
        gp_conn_get_uid(gpcall->connection), gpcall->service->socket);

    return gp_xdr_set[proc].exec_fn(gpcall, arg, res);
}
Beispiel #4
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;
}
bool OSystem_GP32::setSoundCallback(SoundProc proc, void *param) {
	NP("OSys::setSoundCallback()");

	GPSOUNDBUF gpSoundBuf;

	ConfMan.setBool("FM_medium_quality", (g_vars.fmQuality == FM_QUALITY_MED));
	ConfMan.setBool("FM_high_quality", (g_vars.fmQuality == FM_QUALITY_HI));
	//ConfMan.set("output_rate", (int)g_vars.sampleRate);

	if (ConfMan.hasKey("output_rate"))
		_samplesPerSec = ConfMan.getInt("output_rate");
		
	_samplesPerSec = (int)g_vars.sampleRate; //hack
	
	if (_samplesPerSec == 0) {
		return false;
	}

	if (_samplesPerSec < 0)
		_samplesPerSec = SAMPLES_PER_SEC;

	// Originally, we always used 2048 samples. This loop will produce the
	// same result at 22050 Hz, and should hopefully produce something
	// sensible for other frequencies. Note that it must be a power of two.

	uint32 samples = 0x8000;

	for (;;) {
		if ((1000 * samples) / _samplesPerSec < 100)
			break;
		samples >>= 1;
	}

	switch(_samplesPerSec) {
		case 44100:
		case 22050:
		case 11025:
			break;
		default:
			_samplesPerSec = 11025;
	}

	gpSoundBuf.freq = _samplesPerSec;
	gpSoundBuf.format = 16;
	gpSoundBuf.channels = 2;
	gpSoundBuf.samples = samples;
	gpSoundBuf.userdata = param;
	gpSoundBuf.callback = proc;
	gp_soundBufStart(&gpSoundBuf);

	// For Safety...
	GPDEBUG("_samplesPerSec = %d, samples = %d", _samplesPerSec, samples);
	gp_delay(1000);
	return true;
}
Beispiel #6
0
static int parse_flags(const char *value, uint32_t *storage)
{
    char *handle;
    char *token;
    char *str;
    bool add;
    unsigned long int conv;
    uint32_t flagval;
    int i;

    str = strdup(value);
    if (!str) {
        return ENOMEM;
    }

    for (token = strtok_r(str, ", ", &handle);
         token != NULL;
         token = strtok_r(NULL, ", ", &handle)) {
        switch (token[0]) {
        case '+':
            add = true;
            break;
        case '-':
            add = false;
            break;
        default:
            GPERROR("Ignoring flag [%s], missing +/- qualifier.\n", token);
            continue;
        }
        token++;
        for (i = 0; flag_names[i].name != NULL; i++) {
            if (strcasecmp(token, flag_names[i].name) == 0) {
                flagval = flag_names[i].value;
                break;
            }
        }
        if (flag_names[i].name == NULL) {
            conv = strtoul(token, &handle, 0);
            if (conv == 0 || conv == ULONG_MAX || *handle != '\0') {
                GPERROR("Ignoring flag [%s], unrecognized value.\n", token);
                continue;
            }
            flagval = conv;
        }
        GPDEBUG("%s Flag %s (%u).\n", add?"Add":"Remove", token, flagval);
        if (add) *storage |= flagval;
        else *storage &= ~flagval;
    }
    safefree(str);

    return 0;
}
Beispiel #7
0
static void gp_socket_schedule_write(verto_ctx *vctx, struct gp_buffer *wbuf)
{
    verto_ev *ev;

    ev = verto_add_io(vctx, VERTO_EV_FLAG_IO_WRITE,
                      gp_socket_write, wbuf->conn->us.sd);
    if (!ev) {
        GPDEBUG("Failed to add io/write event!\n");
        gp_conn_free(wbuf->conn);
        gp_buffer_free(wbuf);
        return;
    }
    verto_set_private(ev, wbuf, NULL);
}
Beispiel #8
0
static void gp_socket_schedule_read(verto_ctx *vctx, struct gp_buffer *rbuf)
{
    verto_ev *ev;

    ev = verto_add_io(vctx, VERTO_EV_FLAG_IO_READ,
                      gp_socket_read, rbuf->conn->us.sd);
    if (!ev) {
        GPDEBUG("Failed to add io/read event!\n");
        gp_conn_free(rbuf->conn);
        gp_buffer_free(rbuf);
        return;
    }
    verto_set_private(ev, rbuf, NULL);
}
AbstractFilesystemNode *GP32FilesystemNode::parent() const {
	if(_isRoot)
		return 0;

	GP32FilesystemNode *p = new GP32FilesystemNode();
	if (_path.size() > 4) {
		const char *start = _path.c_str();
		const char *end = lastPathComponent(_path);

		p->_path = String(start, end - start);
		p->_isDirectory = true;
		p->_displayName = lastPathComponent(p->_path);
		p->_isRoot = false;
		
		GPDEBUG("%s", p->_path.c_str());
	}

	return p;
}
Beispiel #10
0
int gp_config_init(const char *config_file, const char *config_dir,
                   struct gp_ini_context *ctx)
{
    struct ini_cfgobj *ini_config = NULL;
    int ret;

    /* Within a single file, merge all collisions */
    const uint32_t collision_flags =
      INI_MS_MERGE | INI_MV1S_ALLOW | INI_MV2S_ALLOW;

    if (!ctx) {
        return EINVAL;
    }

    ret = ini_config_create(&ini_config);
    if (ret) {
        return ENOENT;
    }

    if (config_file) {
        ret = gp_config_from_file(config_file, ctx, ini_config,
                                  collision_flags);
        if (ret == ENOENT) {
            GPDEBUG("Expected config file %s but did not find it.\n",
                    config_file);
        } else if (ret) {
            return ret;
        }
    }
    if (config_dir) {
        ret = gp_config_from_dir(config_dir, ctx, &ini_config,
                                 collision_flags);
        if (ret) {
            return ret;
        }
    }

    ctx->private_data = ini_config;

    return 0;
}
Beispiel #11
0
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);
    }
}
Beispiel #12
0
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;
}
Beispiel #13
0
static int gp_config_from_dir(const char *config_dir,
                              struct gp_ini_context *ctx,
                              struct ini_cfgobj **ini_config,
                              const uint32_t collision_flags)
{
    struct ini_cfgobj *result_cfg = NULL;
    struct ref_array *error_list = NULL;
    int ret;

    const char *patterns[] = {
        /* match only files starting with "##-" and ending in ".conf" */
        "^[0-9]\\{2\\}-.\\{1,\\}\\.conf$",
        NULL,
    };

    const char *sections[] = {
        /* match either "gssproxy" or sections that start with "service/" */
        "^gssproxy$",
        "^service/.*$",
        NULL,
    };

    /* Permission check failures silently skip the file, so they are not
     * useful to us. */
    ret = ini_config_augment(*ini_config,
                             config_dir,
                             patterns,
                             sections,
                             NULL, /* check_perm */
                             INI_STOP_ON_ANY, /* error_level */
                             collision_flags,
                             INI_PARSE_NOWRAP,
                             /* do not allow colliding sections with the same
                              * name in different files */
                             INI_MS_ERROR,
                             &result_cfg,
                             &error_list,
                             NULL);
    if (ret) {
        if (error_list) {
            uint32_t i;
            uint32_t len = ref_array_getlen(error_list, &i);
            for (i = 0; i < len; i++) {
                GPDEBUG("Error when reading config directory: %s\n",
                        (const char *) ref_array_get(error_list, i, NULL));
            }
            ref_array_destroy(error_list);
        } else {
            GPDEBUG("Error when reading config directory number: %d\n", ret);
        }
        return ret;
    }

    /* if we read no new files, result_cfg will be NULL */
    if (result_cfg) {
        ini_config_destroy(*ini_config);
        *ini_config = result_cfg;
    }
    if (error_list) {
        ref_array_destroy(error_list);
    }
    return 0;
}
Beispiel #14
0
struct gp_config *read_config(char *config_file, char *config_dir,
                              char *socket_name, int opt_daemonize)
{
    const char *socket = GP_SOCKET_NAME;
    const char *dir = PUBCONF_PATH;
    struct gp_config *cfg;
    int ret;

    cfg = calloc(1, sizeof(struct gp_config));
    if (!cfg) {
        return NULL;
    }

    if (config_file) {
        cfg->config_file = strdup(config_file);
        if (!cfg->config_file) {
            ret = ENOMEM;
            goto done;
        }
    } else {
        ret = asprintf(&cfg->config_file, "%s/gssproxy.conf", PUBCONF_PATH);
        if (ret == -1) {
            goto done;
        }
    }

    if (config_dir) dir = config_dir;

    cfg->config_dir = strdup(dir);
    if (!cfg->config_dir) {
        ret = ENOMEM;
        goto done;
    }

    if (socket_name) socket = socket_name;

    cfg->socket_name = strdup(socket);
    if (cfg->socket_name == NULL) {
        ret = ENOMEM;
        goto done;
    }

    switch (opt_daemonize) {
    case 0:
        /* daemonize by default */
    case 1:
        cfg->daemonize = true;
        break;
    case 2:
        cfg->daemonize = false;
        break;
    }

    ret = load_config(cfg);
    if (ret) {
        GPDEBUG("Config file(s) not found!\n");
    }

done:
    if (ret) {
        /* recursively frees cfg */
        free_config(&cfg);
        return NULL;
    }

    return cfg;
}
Beispiel #15
0
static int load_services(struct gp_config *cfg, struct gp_ini_context *ctx)
{
    int num_sec;
    char *secname = NULL;
    const char *value;
    char *vcopy;
    char *token;
    char *handle;
    int valnum;
    int ret;
    int i, n;

    num_sec = gp_config_get_nsec(ctx);

    /* allocate enough space for num_sec services,
     * we won't waste too much space by overallocating */
    cfg->svcs = calloc(num_sec, sizeof(struct gp_service *));
    if (!cfg->svcs) {
        ret = ENOMEM;
        goto done;
    }

    for (i = 0; i < num_sec; i++) {
        secname = gp_config_get_secname(ctx, i);

        ret = strncmp(secname, "service/", 8);
        if (ret == 0) {
            n = cfg->num_svcs;
            cfg->svcs[n] = calloc(1, sizeof(struct gp_service));
            if (!cfg->svcs[n]) {
                ret = ENOMEM;
                goto done;
            }
            cfg->num_svcs++;

            /* by default allow both */
            cfg->svcs[n]->cred_usage = GSS_C_BOTH;

            cfg->svcs[n]->name = strdup(secname + 8);
            if (!cfg->svcs[n]->name) {
                ret = ENOMEM;
                goto done;
            }

            /* euid can be a string or an int */
            ret = gp_config_get_int(ctx, secname, "euid", &valnum);
            if (ret != 0) {
                ret = gp_config_get_string(ctx, secname, "euid", &value);
                if (ret == 0) {
                    struct passwd *eu_passwd; /* static; do not free */

                    errno = 0; /* needs to be 0; otherwise it won't be set */
                    eu_passwd = getpwnam(value);
                    if (!eu_passwd) {
                        ret = errno;
                        if (ret == 0) { /* not that it gets set anyway... */
                            ret = ENOENT;
                        }
                    } else {
                        valnum = eu_passwd->pw_uid;
                    }
                }
                if (ret != 0) {
                    /* if euid is missing or there is an error retrieving it
                     * return an error and end. This is a fatal condition. */
                    if (ret == ENOENT) {
                        GPERROR("Option 'euid' is missing from [%s].\n", secname);
                        ret = EINVAL;
                    }
                    gp_service_free(cfg->svcs[n]);
                    cfg->num_svcs--;
                    safefree(secname);
                    goto done;
                }
            }
            cfg->svcs[n]->euid = valnum;

            ret = gp_config_get_string(ctx, secname, "allow_any_uid", &value);
            if (ret == 0) {
                if (gp_boolean_is_true(value)) {
                    cfg->svcs[n]->any_uid = true;
                }
            }

            ret = gp_config_get_string(ctx, secname, "trusted", &value);
            if (ret == 0) {
                if (gp_boolean_is_true(value)) {
                    cfg->svcs[n]->trusted = true;
                }
            }

            ret = gp_config_get_string(ctx, secname, "kernel_nfsd", &value);
            if (ret == 0) {
                if (gp_boolean_is_true(value)) {
                    cfg->svcs[n]->kernel_nfsd = true;
                }
            }

            ret = gp_config_get_string(ctx, secname, "impersonate", &value);
            if (ret == 0) {
                if (gp_boolean_is_true(value)) {
                    cfg->svcs[n]->impersonate = true;
                }
            }

            ret = gp_config_get_string(ctx, secname, "socket", &value);
            if (ret == 0) {
                cfg->svcs[n]->socket = strdup(value);
                if (!cfg->svcs[n]->socket) {
                    ret = ENOMEM;
                    goto done;
                }
            }

            ret = setup_service_creds_handle(cfg->svcs[n]);
            if (ret) {
                goto done;
            }

            ret = gp_config_get_string(ctx, secname, "mechs", &value);
            if (ret != 0) {
                /* if mechs is missing or there is an error retrieving it
                 * return an error and end. This is a fatal condition. */
                if (ret == ENOENT) {
                    GPERROR("Option 'mechs' is missing from [%s].\n", secname);
                    ret = EINVAL;
                }
                gp_service_free(cfg->svcs[n]);
                cfg->num_svcs--;
                safefree(secname);
                goto done;
            }

            vcopy = strdup(value);
            if (!vcopy) {
                ret = ENOMEM;
                goto done;
            }
            token = strtok_r(vcopy, ", ", &handle);
            do {

                ret = strcmp(value, "krb5");
                if (ret == 0) {
                    ret = get_krb5_mech_cfg(cfg->svcs[n], ctx, secname);
                    if (ret == 0) {
                        cfg->svcs[n]->mechs |= GP_CRED_KRB5;
                    } else {
                        GPERROR("Failed to read krb5 config for %s.\n",
                                secname);
                        safefree(vcopy);
                        return ret;
                    }
                } else {
                    GPERROR("Unknown mech: %s in [%s], ignoring.\n",
                            token, secname);
                }

                token = strtok_r(NULL, ", ", &handle);
            } while (token != NULL);
            safefree(vcopy);

            if (cfg->svcs[n]->mechs == 0) {
                GPDEBUG("No mechs found for [%s], ignoring.\n", secname);
                gp_service_free(cfg->svcs[n]);
                cfg->num_svcs--;
                safefree(secname);
                continue;
            }

            ret = gp_config_get_string(ctx, secname,
                                       "selinux_context", &value);
            if (ret == 0) {
                cfg->svcs[n]->selinux_ctx = SELINUX_context_new(value);
                if (!cfg->svcs[n]->selinux_ctx) {
                    ret = EINVAL;
                    goto done;
                }
            }

            ret = gp_config_get_string(ctx, secname, "cred_usage", &value);
            if (ret == 0) {
                if (strcasecmp(value, "initiate") == 0) {
                    cfg->svcs[n]->cred_usage = GSS_C_INITIATE;
                } else if (strcasecmp(value, "accept") == 0) {
                    cfg->svcs[n]->cred_usage = GSS_C_ACCEPT;
                } else if (strcasecmp(value, "both") == 0) {
                    cfg->svcs[n]->cred_usage = GSS_C_BOTH;
                } else {
                    GPDEBUG("Invalid value '%s' for cred_usage in [%s].\n",
                            value, secname);
                    ret = EINVAL;
                    goto done;
                }
            }

            cfg->svcs[n]->filter_flags = DEFAULT_FILTERED_FLAGS;
            ret = gp_config_get_string(ctx, secname, "filter_flags", &value);
            if (ret == 0) {
                parse_flags(value, &cfg->svcs[n]->filter_flags);
            }

            cfg->svcs[n]->enforce_flags = DEFAULT_ENFORCED_FLAGS;
            ret = gp_config_get_string(ctx, secname, "enforce_flags", &value);
            if (ret == 0) {
                ret = parse_flags(value, &cfg->svcs[n]->enforce_flags);
                if (ret) goto done;
            }
        }
        safefree(secname);
    }

    if (cfg->num_svcs == 0) {
        GPERROR("No service sections configured!\n");
        return ENOENT;
    }

    ret = check_services(cfg);

done:
    safefree(secname);
    return ret;
}