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; }
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); }
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; }
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; }
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); }
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; }
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; }
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; }
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; }
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; }
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; }