int main(int argc, char **argv) { const char *guid_str; const char *attr_str; const char *varname; const char *keyfilename; const char *certfilename; varsign_context *ctx; bool include_attrs; int c = 0; unsigned char no_signing = 0; unsigned char no_repack = 0; ctx = talloc_zero(NULL, varsign_context); keyfilename = NULL; certfilename = NULL; guid_str = NULL; attr_str= NULL; include_attrs = false; for (;;) { int idx; c = getopt_long(argc, argv, "o:g:a:k:c:n:ivVh", options, &idx); if (c == -1) { break; } switch (c) { case 'o': ctx->outfilename = optarg; break; case 'g': guid_str = optarg; break; case 'a': attr_str = optarg; break; case 'k': keyfilename = optarg; break; case 'c': certfilename = optarg; break; case 'i': include_attrs = true; break; case 'v': ctx->verbose = 1; break; case 'V': version(); return EXIT_SUCCESS; case 'n': no_signing = 1; break; case 'N': no_signing = 1; break; case 'r': no_repack = 1; do_direct = 1; break; case 'R': no_repack = 1; do_direct = 1; break; case 'h': usage(); return EXIT_SUCCESS; } } if (argc != (optind + 2)) { usage(); return EXIT_FAILURE; } if ((!keyfilename) && (!no_signing)) { fprintf(stderr, "No signing key specified\n"); return EXIT_FAILURE; } if ((!certfilename) && (!no_signing)) { fprintf(stderr, "No signing certificate specified\n"); return EXIT_FAILURE; } /* initialise openssl */ OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); ERR_load_crypto_strings(); /* set up the variable signing context */ varname = argv[optind]; set_varname(ctx, varname); ctx->infilename = argv[optind+1]; if (!ctx->outfilename) { set_default_outfilename(ctx); } if (attr_str) { ctx->var_attrs = parse_attrs(attr_str); if (ctx->var_attrs == attr_invalid) { return EXIT_FAILURE; } } else { ctx->var_attrs = default_attrs; } if (guid_str) { if (parse_guid(guid_str, &ctx->var_guid)) { fprintf(stderr, "Invalid GUID '%s'\n", guid_str); return EXIT_FAILURE; } } else { set_default_guid(ctx, varname); } if (fileio_read_file(ctx, ctx->infilename, &ctx->data, &ctx->data_len)) { return EXIT_FAILURE; } if (!no_signing) { ctx->key = fileio_read_pkey(keyfilename); if (!ctx->key) { return EXIT_FAILURE; } ctx->cert = fileio_read_cert(certfilename); if (!ctx->cert) { return EXIT_FAILURE; } } /* do the signing */ if (add_auth_descriptor(ctx, no_signing)) { return EXIT_FAILURE; } /* write the resulting image */ if (write_signed(ctx, include_attrs, no_repack)) { return EXIT_FAILURE; } return EXIT_SUCCESS; }
static int demux_open_tv(demuxer_t *demuxer, enum demux_check check) { tvi_handle_t *tvh; sh_video_t *sh_video; sh_audio_t *sh_audio = NULL; const tvi_functions_t *funcs; if (check > DEMUX_CHECK_REQUEST || demuxer->stream->type != STREAMTYPE_TV) return -1; demuxer->priv=NULL; if(!(tvh=tv_begin(demuxer->stream->priv, demuxer->log))) return -1; if (!tvh->functions->init(tvh->priv)) return -1; tvh->demuxer = demuxer; if (!open_tv(tvh)){ tv_uninit(tvh); return -1; } funcs = tvh->functions; demuxer->priv=tvh; struct sh_stream *sh_v = new_sh_stream(demuxer, STREAM_VIDEO); sh_video = sh_v->video; /* get IMAGE FORMAT */ int fourcc; funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FORMAT, &fourcc); if (fourcc == MP_FOURCC_MJPEG) { sh_v->codec = "mjpeg"; } else { sh_v->codec = "rawvideo"; sh_v->format = fourcc; } /* set FPS and FRAMETIME */ if(!sh_video->fps) { float tmp; if (funcs->control(tvh->priv, TVI_CONTROL_VID_GET_FPS, &tmp) != TVI_CONTROL_TRUE) sh_video->fps = 25.0f; /* on PAL */ else sh_video->fps = tmp; } if (tvh->tv_param->fps != -1.0f) sh_video->fps = tvh->tv_param->fps; /* If playback only mode, go to immediate mode, fail silently */ if(tvh->tv_param->immediate == 1) { funcs->control(tvh->priv, TVI_CONTROL_IMMEDIATE, 0); tvh->tv_param->noaudio = 1; } /* set width */ funcs->control(tvh->priv, TVI_CONTROL_VID_GET_WIDTH, &sh_video->disp_w); /* set height */ funcs->control(tvh->priv, TVI_CONTROL_VID_GET_HEIGHT, &sh_video->disp_h); demuxer->seekable = 0; /* here comes audio init */ if (tvh->tv_param->noaudio == 0 && funcs->control(tvh->priv, TVI_CONTROL_IS_AUDIO, 0) == TVI_CONTROL_TRUE) { int audio_format; /* yeah, audio is present */ funcs->control(tvh->priv, TVI_CONTROL_AUD_SET_SAMPLERATE, &tvh->tv_param->audiorate); if (funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_FORMAT, &audio_format) != TVI_CONTROL_TRUE) goto no_audio; switch(audio_format) { case AF_FORMAT_U8: case AF_FORMAT_S8: case AF_FORMAT_U16_LE: case AF_FORMAT_U16_BE: case AF_FORMAT_S16_LE: case AF_FORMAT_S16_BE: case AF_FORMAT_S32_LE: case AF_FORMAT_S32_BE: break; case AF_FORMAT_MPEG2: default: MP_ERR(tvh, "Audio type '%s' unsupported!\n", af_fmt_to_str(audio_format)); goto no_audio; } struct sh_stream *sh_a = new_sh_stream(demuxer, STREAM_AUDIO); sh_audio = sh_a->audio; funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_SAMPLERATE, &sh_audio->samplerate); int nchannels = sh_audio->channels.num; funcs->control(tvh->priv, TVI_CONTROL_AUD_GET_CHANNELS, &nchannels); mp_chmap_from_channels(&sh_audio->channels, nchannels); sh_a->codec = "mp-pcm"; sh_a->format = audio_format; int samplesize = af_fmt2bits(audio_format) / 8; sh_audio->i_bps = sh_audio->samplerate * samplesize * sh_audio->channels.num; // emulate WF for win32 codecs: sh_audio->wf = talloc_zero(sh_audio, MP_WAVEFORMATEX); sh_audio->wf->wFormatTag = sh_a->format; sh_audio->wf->nChannels = sh_audio->channels.num; sh_audio->wf->wBitsPerSample = samplesize * 8; sh_audio->wf->nSamplesPerSec = sh_audio->samplerate; sh_audio->wf->nBlockAlign = samplesize * sh_audio->channels.num; sh_audio->wf->nAvgBytesPerSec = sh_audio->i_bps; MP_VERBOSE(tvh, " TV audio: %d channels, %d bits, %d Hz\n", sh_audio->wf->nChannels, sh_audio->wf->wBitsPerSample, sh_audio->wf->nSamplesPerSec); } no_audio: if(!(funcs->start(tvh->priv))){ // start failed :( tv_uninit(tvh); return -1; } /* set color eq */ tv_set_color_options(tvh, TV_COLOR_BRIGHTNESS, tvh->tv_param->brightness); tv_set_color_options(tvh, TV_COLOR_HUE, tvh->tv_param->hue); tv_set_color_options(tvh, TV_COLOR_SATURATION, tvh->tv_param->saturation); tv_set_color_options(tvh, TV_COLOR_CONTRAST, tvh->tv_param->contrast); if(tvh->tv_param->gain!=-1) if(funcs->control(tvh->priv,TVI_CONTROL_VID_SET_GAIN,&tvh->tv_param->gain)!=TVI_CONTROL_TRUE) MP_WARN(tvh, "Unable to set gain control!\n"); return 0; }
/** Register an xlat function. * * @param[in] name xlat name. * @param[in] func xlat function to be called. * @param[in] escape function to sanitize any sub expansions passed to the xlat function. * @param[in] instance of module that's registering the xlat function. * @return 0 on success, -1 on failure */ int xlat_register(char const *name, RAD_XLAT_FUNC func, RADIUS_ESCAPE_STRING escape, void *instance) { xlat_t *c; xlat_t my_xlat; rbnode_t *node; if (!name || !*name) { DEBUG("xlat_register: Invalid xlat name"); return -1; } /* * First time around, build up the tree... * * FIXME: This code should be hoisted out of this function, * and into a global "initialization". But it isn't critical... */ if (!xlat_root) { #ifdef WITH_UNLANG int i; #endif xlat_root = rbtree_create(xlat_cmp, NULL, 0); if (!xlat_root) { DEBUG("xlat_register: Failed to create tree"); return -1; } #ifdef WITH_UNLANG for (i = 0; xlat_foreach_names[i] != NULL; i++) { xlat_register(xlat_foreach_names[i], xlat_foreach, NULL, &xlat_inst[i]); c = xlat_find(xlat_foreach_names[i]); rad_assert(c != NULL); c->internal = true; } #endif #define XLAT_REGISTER(_x) xlat_register(STRINGIFY(_x), xlat_ ## _x, NULL, NULL); \ c = xlat_find(STRINGIFY(_x)); \ rad_assert(c != NULL); \ c->internal = true XLAT_REGISTER(integer); XLAT_REGISTER(strlen); XLAT_REGISTER(length); XLAT_REGISTER(hex); XLAT_REGISTER(string); XLAT_REGISTER(xlat); XLAT_REGISTER(module); XLAT_REGISTER(debug_attr); xlat_register("debug", xlat_debug, NULL, &xlat_inst[0]); c = xlat_find("debug"); rad_assert(c != NULL); c->internal = true; } /* * If it already exists, replace the instance. */ strlcpy(my_xlat.name, name, sizeof(my_xlat.name)); my_xlat.length = strlen(my_xlat.name); c = rbtree_finddata(xlat_root, &my_xlat); if (c) { if (c->internal) { DEBUG("xlat_register: Cannot re-define internal xlat"); return -1; } c->func = func; c->escape = escape; c->instance = instance; return 0; } /* * Doesn't exist. Create it. */ c = talloc_zero(xlat_root, xlat_t); c->func = func; c->escape = escape; strlcpy(c->name, name, sizeof(c->name)); c->length = strlen(c->name); c->instance = instance; node = rbtree_insert_node(xlat_root, c); if (!node) { talloc_free(c); return -1; } /* * Ensure that the data is deleted when the node is * deleted. * * @todo: Maybe this should be the other way around... * when a thing IN the tree is deleted, it's automatically * removed from the tree. But for now, this works. */ (void) talloc_steal(node, c); return 0; }
int main(int argc, char **argv) { RADIUS_PACKET *req; char *p; int c; uint16_t port = 0; char *filename = NULL; FILE *fp; int id; int force_af = AF_UNSPEC; static fr_log_t radclient_log = { .colourise = true, .fd = STDOUT_FILENO, .dst = L_DST_STDOUT, .file = NULL, .debug_file = NULL, }; radlog_init(&radclient_log, false); /* * We probably don't want to free the talloc autofree context * directly, so we'll allocate a new context beneath it, and * free that before any leak reports. */ TALLOC_CTX *autofree = talloc_init("main"); id = ((int)getpid() & 0xff); fr_debug_flag = 0; set_radius_dir(autofree, RADIUS_DIR); while ((c = getopt(argc, argv, "46c:d:D:f:hi:qst:r:S:xXv")) != EOF) { switch(c) { case '4': force_af = AF_INET; break; case '6': force_af = AF_INET6; break; case 'd': set_radius_dir(autofree, optarg); break; case 'D': main_config.dictionary_dir = talloc_typed_strdup(NULL, optarg); break; case 'f': filename = optarg; break; case 'q': do_output = 0; break; case 'x': debug_flag++; fr_debug_flag++; break; case 'X': #if 0 sha1_data_problems = 1; /* for debugging only */ #endif break; case 'r': if (!isdigit((int) *optarg)) usage(); retries = atoi(optarg); break; case 'i': if (!isdigit((int) *optarg)) usage(); id = atoi(optarg); if ((id < 0) || (id > 255)) { usage(); } break; case 's': do_summary = 1; break; case 't': if (!isdigit((int) *optarg)) usage(); timeout = atof(optarg); break; case 'v': printf("radeapclient: $Id: 69643e042c5a7c9053977756a5623e3c07598f2e $ built on " __DATE__ " at " __TIME__ "\n"); exit(0); break; case 'S': fp = fopen(optarg, "r"); if (!fp) { fprintf(stderr, "radclient: Error opening %s: %s\n", optarg, fr_syserror(errno)); exit(1); } if (fgets(filesecret, sizeof(filesecret), fp) == NULL) { fprintf(stderr, "radclient: Error reading %s: %s\n", optarg, fr_syserror(errno)); exit(1); } fclose(fp); /* truncate newline */ p = filesecret + strlen(filesecret) - 1; while ((p >= filesecret) && (*p < ' ')) { *p = '\0'; --p; } if (strlen(filesecret) < 2) { fprintf(stderr, "radclient: Secret in %s is too short\n", optarg); exit(1); } secret = filesecret; break; case 'h': default: usage(); break; } } argc -= (optind - 1); argv += (optind - 1); if ((argc < 3) || ((!secret) && (argc < 4))) { usage(); } if (!main_config.dictionary_dir) { main_config.dictionary_dir = DICTDIR; } /* * Read the distribution dictionaries first, then * the ones in raddb. */ DEBUG2("including dictionary file %s/%s", main_config.dictionary_dir, RADIUS_DICTIONARY); if (dict_init(main_config.dictionary_dir, RADIUS_DICTIONARY) != 0) { ERROR("Errors reading dictionary: %s", fr_strerror()); exit(1); } /* * It's OK if this one doesn't exist. */ int rcode = dict_read(radius_dir, RADIUS_DICTIONARY); if (rcode == -1) { ERROR("Errors reading %s/%s: %s", radius_dir, RADIUS_DICTIONARY, fr_strerror()); exit(1); } /* * We print this after reading it. That way if * it doesn't exist, it's OK, and we don't print * anything. */ if (rcode == 0) { DEBUG2("including dictionary file %s/%s", radius_dir, RADIUS_DICTIONARY); } req = rad_alloc(NULL, 1); if (!req) { fr_perror("radclient"); exit(1); } #if 0 { FILE *randinit; if((randinit = fopen("/dev/urandom", "r")) == NULL) { perror("/dev/urandom"); } else { fread(randctx.randrsl, 256, 1, randinit); fclose(randinit); } } fr_randinit(&randctx, 1); #endif req->id = id; /* * Resolve hostname. */ if (force_af == AF_UNSPEC) force_af = AF_INET; req->dst_ipaddr.af = force_af; if (strcmp(argv[1], "-") != 0) { char const *hostname = argv[1]; char const *portname = argv[1]; char buffer[256]; if (*argv[1] == '[') { /* IPv6 URL encoded */ p = strchr(argv[1], ']'); if ((size_t) (p - argv[1]) >= sizeof(buffer)) { usage(); } memcpy(buffer, argv[1] + 1, p - argv[1] - 1); buffer[p - argv[1] - 1] = '\0'; hostname = buffer; portname = p + 1; } p = strchr(portname, ':'); if (p && (strchr(p + 1, ':') == NULL)) { *p = '\0'; portname = p + 1; } else { portname = NULL; } if (ip_hton(&req->dst_ipaddr, force_af, hostname, false) < 0) { fprintf(stderr, "radclient: Failed to find IP address for host %s: %s\n", hostname, fr_syserror(errno)); exit(1); } /* * Strip port from hostname if needed. */ if (portname) port = atoi(portname); } /* * See what kind of request we want to send. */ if (strcmp(argv[2], "auth") == 0) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = PW_CODE_AUTHENTICATION_REQUEST; } else if (strcmp(argv[2], "acct") == 0) { if (port == 0) port = getport("radacct"); if (port == 0) port = PW_ACCT_UDP_PORT; req->code = PW_CODE_ACCOUNTING_REQUEST; do_summary = 0; } else if (strcmp(argv[2], "status") == 0) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = PW_CODE_STATUS_SERVER; } else if (strcmp(argv[2], "disconnect") == 0) { if (port == 0) port = PW_POD_UDP_PORT; req->code = PW_CODE_DISCONNECT_REQUEST; } else if (isdigit((int) argv[2][0])) { if (port == 0) port = getport("radius"); if (port == 0) port = PW_AUTH_UDP_PORT; req->code = atoi(argv[2]); } else { usage(); } req->dst_port = port; /* * Add the secret. */ if (argv[3]) secret = argv[3]; /* * Read valuepairs. * Maybe read them, from stdin, if there's no * filename, or if the filename is '-'. */ if (filename && (strcmp(filename, "-") != 0)) { fp = fopen(filename, "r"); if (!fp) { fprintf(stderr, "radclient: Error opening %s: %s\n", filename, fr_syserror(errno)); exit(1); } } else { fp = stdin; } /* * Send request. */ if ((req->sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("radclient: socket: "); exit(1); } while(!filedone) { if (req->vps) pairfree(&req->vps); if (readvp2(&req->vps, NULL, fp, &filedone) < 0) { fr_perror("radeapclient"); break; } sendrecv_eap(req); } if(do_summary) { printf("\n\t Total approved auths: %d\n", totalapp); printf("\t Total denied auths: %d\n", totaldeny); } talloc_free(autofree); return 0; } /* * given a radius request with some attributes in the EAP range, build * them all into a single EAP-Message body. * * Note that this function will build multiple EAP-Message bodies * if there are multiple eligible EAP-types. This is incorrect, as the * recipient will in fact concatenate them. * * XXX - we could break the loop once we process one type. Maybe this * just deserves an assert? * */ static void map_eap_methods(RADIUS_PACKET *req) { VALUE_PAIR *vp, *vpnext; int id, eapcode; int eap_method; eap_packet_t *pt_ep = talloc_zero(req, eap_packet_t); vp = pairfind(req->vps, ATTRIBUTE_EAP_ID, 0, TAG_ANY); if(!vp) { id = ((int)getpid() & 0xff); } else { id = vp->vp_integer; } vp = pairfind(req->vps, ATTRIBUTE_EAP_CODE, 0, TAG_ANY); if(!vp) { eapcode = PW_EAP_REQUEST; } else { eapcode = vp->vp_integer; } for(vp = req->vps; vp != NULL; vp = vpnext) { /* save it in case it changes! */ vpnext = vp->next; if(vp->da->attr >= ATTRIBUTE_EAP_BASE && vp->da->attr < ATTRIBUTE_EAP_BASE+256) { break; } } if(!vp) { return; } eap_method = vp->da->attr - ATTRIBUTE_EAP_BASE; switch(eap_method) { case PW_EAP_IDENTITY: case PW_EAP_NOTIFICATION: case PW_EAP_NAK: case PW_EAP_MD5: case PW_EAP_OTP: case PW_EAP_GTC: case PW_EAP_TLS: case PW_EAP_LEAP: case PW_EAP_TTLS: case PW_EAP_PEAP: default: /* * no known special handling, it is just encoded as an * EAP-message with the given type. */ /* nuke any existing EAP-Messages */ pairdelete(&req->vps, PW_EAP_MESSAGE, 0, TAG_ANY); pt_ep->code = eapcode; pt_ep->id = id; pt_ep->type.num = eap_method; pt_ep->type.length = vp->length; pt_ep->type.data = talloc_memdup(vp, vp->vp_octets, vp->length); talloc_set_type(pt_ep->type.data, uint8_t); eap_basic_compose(req, pt_ep); } }
int main(int argc, char *argv[]) { int c; int num_networks = 1; int num_workers = 2; uint16_t port16 = 0; TALLOC_CTX *autofree = talloc_autofree_context(); fr_schedule_t *sched; fr_listen_t listen = { .app_io = &app_io, .app = &test_app }; fr_listen_test_t *app_io_inst; listen.app_io_instance = app_io_inst = talloc_zero(autofree, fr_listen_test_t); fr_time_start(); fr_log_init(&default_log, false); default_log.colourise = true; memset(&my_ipaddr, 0, sizeof(my_ipaddr)); my_ipaddr.af = AF_INET; my_ipaddr.prefix = 32; my_ipaddr.addr.v4.s_addr = htonl(INADDR_LOOPBACK); my_port = 1812; while ((c = getopt(argc, argv, "i:n:s:w:x")) != EOF) switch (c) { case 'i': if (fr_inet_pton_port(&my_ipaddr, &port16, optarg, -1, AF_INET, true, false) < 0) { fr_perror("Failed parsing ipaddr"); exit(EXIT_FAILURE); } my_port = port16; break; case 'n': num_networks = atoi(optarg); if ((num_networks <= 0) || (num_networks > 16)) usage(); break; case 's': secret = optarg; break; case 'w': num_workers = atoi(optarg); if ((num_workers <= 0) || (num_workers > 1024)) usage(); break; case 'x': debug_lvl++; fr_debug_lvl++; break; case 'h': default: usage(); } #if 0 argc -= (optind - 1); argv += (optind - 1); #endif app_io_inst->ipaddr = my_ipaddr; app_io_inst->port = my_port; sched = fr_schedule_create(autofree, NULL, &default_log, debug_lvl, num_networks, num_workers, NULL, NULL); if (!sched) { fprintf(stderr, "schedule_test: Failed to create scheduler\n"); exit(EXIT_FAILURE); } if (listen.app_io->open(listen.app_io_instance, listen.app_io_instance) < 0) exit(EXIT_FAILURE); #if 0 /* * Set up the KQ filter for reading. */ EV_SET(&events[0], sockfd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, NULL); if (kevent(kq_master, events, 1, NULL, 0, NULL) < 0) { fr_perror("Failed setting KQ for EVFILT_READ"); exit(EXIT_FAILURE); } #endif (void) fr_fault_setup(autofree, NULL, argv[0]); (void) fr_schedule_listen_add(sched, &listen); sleep(10); (void) fr_schedule_destroy(sched); exit(EXIT_SUCCESS); }
/* * given a radius request with some attributes in the EAP range, build * them all into a single EAP-Message body. * * Note that this function will build multiple EAP-Message bodies * if there are multiple eligible EAP-types. This is incorrect, as the * recipient will in fact concatenate them. * * XXX - we could break the loop once we process one type. Maybe this * just deserves an assert? * */ static void map_eap_methods(RADIUS_PACKET *req) { VALUE_PAIR *vp, *vpnext; int id, eapcode; int eap_method; eap_packet_t *pt_ep = talloc_zero(req, eap_packet_t); vp = pairfind(req->vps, ATTRIBUTE_EAP_ID, 0, TAG_ANY); if(!vp) { id = ((int)getpid() & 0xff); } else { id = vp->vp_integer; } vp = pairfind(req->vps, ATTRIBUTE_EAP_CODE, 0, TAG_ANY); if(!vp) { eapcode = PW_EAP_REQUEST; } else { eapcode = vp->vp_integer; } for(vp = req->vps; vp != NULL; vp = vpnext) { /* save it in case it changes! */ vpnext = vp->next; if(vp->da->attr >= ATTRIBUTE_EAP_BASE && vp->da->attr < ATTRIBUTE_EAP_BASE+256) { break; } } if(!vp) { return; } eap_method = vp->da->attr - ATTRIBUTE_EAP_BASE; switch(eap_method) { case PW_EAP_IDENTITY: case PW_EAP_NOTIFICATION: case PW_EAP_NAK: case PW_EAP_MD5: case PW_EAP_OTP: case PW_EAP_GTC: case PW_EAP_TLS: case PW_EAP_LEAP: case PW_EAP_TTLS: case PW_EAP_PEAP: default: /* * no known special handling, it is just encoded as an * EAP-message with the given type. */ /* nuke any existing EAP-Messages */ pairdelete(&req->vps, PW_EAP_MESSAGE, 0, TAG_ANY); pt_ep->code = eapcode; pt_ep->id = id; pt_ep->type.num = eap_method; pt_ep->type.length = vp->length; pt_ep->type.data = talloc_memdup(vp, vp->vp_octets, vp->length); talloc_set_type(pt_ep->type.data, uint8_t); eap_basic_compose(req, pt_ep); } }
/** \details Opens a specific message and retrieves a MAPI object that can be used to get or set message properties. This function opens a specific message defined by a combination of object store, folder ID, and message ID and which read/write access is defined by ulFlags. \param obj_store the store to read from \param id_folder the folder ID \param id_message the message ID \param obj_message the resulting message object \param ulFlags Possible ulFlags values: - 0x0: read only access - 0x1: ReadWrite - 0x3: Create - 0x4: OpenSoftDeleted \return MAPI_E_SUCCESS on success, otherwise MAPI error. \note Developers may also call GetLastError() to retrieve the last MAPI error code. Possible MAPI error codes are: - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized - MAPI_E_INVALID_PARAMETER: obj_store is undefined - MAPI_E_CALL_FAILED: A network problem was encountered during the transaction \sa MAPIInitialize, GetLastError */ _PUBLIC_ enum MAPISTATUS OpenMessage(mapi_object_t *obj_store, mapi_id_t id_folder, mapi_id_t id_message, mapi_object_t *obj_message, uint8_t ulFlags) { struct mapi_context *mapi_ctx; struct mapi_request *mapi_request; struct mapi_response *mapi_response; struct EcDoRpc_MAPI_REQ *mapi_req; struct OpenMessage_req request; struct OpenMessage_repl *reply; struct mapi_session *session; mapi_object_message_t *message; struct SPropValue lpProp; const char *tstring; NTSTATUS status; enum MAPISTATUS retval; uint32_t size = 0; TALLOC_CTX *mem_ctx; uint32_t i = 0; uint8_t logon_id; /* Sanity checks */ OPENCHANGE_RETVAL_IF(!obj_store, MAPI_E_INVALID_PARAMETER, NULL); session = mapi_object_get_session(obj_store); OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL); mapi_ctx = session->mapi_ctx; OPENCHANGE_RETVAL_IF(!mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL); if ((retval = mapi_object_get_logon_id(obj_store, &logon_id)) != MAPI_E_SUCCESS) return retval; mem_ctx = talloc_named(session, 0, "OpenMessage"); /* Fill the OpenMessage operation */ request.handle_idx = 0x1; request.CodePageId = 0xfff; request.FolderId = id_folder; request.OpenModeFlags = (enum OpenMessage_OpenModeFlags)ulFlags; request.MessageId = id_message; size = sizeof (uint8_t) + sizeof(uint16_t) + sizeof(mapi_id_t) + sizeof(uint8_t) + sizeof(mapi_id_t); /* Fill the MAPI_REQ request */ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ); mapi_req->opnum = op_MAPI_OpenMessage; mapi_req->logon_id = logon_id; mapi_req->handle_idx = 0; mapi_req->u.mapi_OpenMessage = request; size += 5; /* Fill the mapi_request structure */ mapi_request = talloc_zero(mem_ctx, struct mapi_request); mapi_request->mapi_len = size + sizeof (uint32_t) * 2; mapi_request->length = size; mapi_request->mapi_req = mapi_req; mapi_request->handles = talloc_array(mem_ctx, uint32_t, 2); mapi_request->handles[0] = mapi_object_get_handle(obj_store); mapi_request->handles[1] = 0xffffffff; status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response); OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx); OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx); retval = mapi_response->mapi_repl->error_code; OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx); OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response); /* Set object session and handle */ mapi_object_set_session(obj_message, session); mapi_object_set_handle(obj_message, mapi_response->handles[1]); mapi_object_set_logon_id(obj_message, logon_id); /* Store OpenMessage reply data */ reply = &mapi_response->mapi_repl->u.mapi_OpenMessage; message = talloc_zero((TALLOC_CTX *)session, mapi_object_message_t); tstring = get_TypedString(&reply->SubjectPrefix); if (tstring) { message->SubjectPrefix = talloc_strdup((TALLOC_CTX *)message, tstring); } tstring = get_TypedString(&reply->NormalizedSubject); if (tstring) { message->NormalizedSubject = talloc_strdup((TALLOC_CTX *)message, tstring); } message->cValues = reply->RecipientColumns.cValues; message->SRowSet.cRows = reply->RowCount; message->SRowSet.aRow = talloc_array((TALLOC_CTX *)message, struct SRow, reply->RowCount + 1); message->SPropTagArray.cValues = reply->RecipientColumns.cValues; message->SPropTagArray.aulPropTag = talloc_steal(message, reply->RecipientColumns.aulPropTag); for (i = 0; i < reply->RowCount; i++) { emsmdb_get_SRow((TALLOC_CTX *)message, &(message->SRowSet.aRow[i]), &message->SPropTagArray, reply->RecipientRows[i].RecipientRow.prop_count, &reply->RecipientRows[i].RecipientRow.prop_values, reply->RecipientRows[i].RecipientRow.layout, 1); lpProp.ulPropTag = PR_RECIPIENT_TYPE; lpProp.value.l = reply->RecipientRows[i].RecipientType; SRow_addprop(&(message->SRowSet.aRow[i]), lpProp); lpProp.ulPropTag = PR_INTERNET_CPID; lpProp.value.l = reply->RecipientRows[i].CodePageId; SRow_addprop(&(message->SRowSet.aRow[i]), lpProp); } /* add SPropTagArray elements we automatically append to SRow */ SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_RECIPIENT_TYPE); SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_INTERNET_CPID); obj_message->private_data = (void *) message; talloc_free(mapi_response); talloc_free(mem_ctx); return MAPI_E_SUCCESS; }
static int mod_session_init (void *instance, eap_handler_t *handler) { pwd_session_t *session; eap_pwd_t *inst = (eap_pwd_t *)instance; VALUE_PAIR *vp; pwd_id_packet_t *packet; if (!inst || !handler) { ERROR("rlm_eap_pwd: Initiate, NULL data provided"); return 0; } /* * make sure the server's been configured properly */ if (!inst->server_id) { ERROR("rlm_eap_pwd: Server ID is not configured"); return 0; } switch (inst->group) { case 19: case 20: case 21: case 25: case 26: break; default: ERROR("rlm_eap_pwd: Group is not supported"); return 0; } if ((session = talloc_zero(handler, pwd_session_t)) == NULL) return 0; talloc_set_destructor(session, _free_pwd_session); /* * set things up so they can be free'd reliably */ session->group_num = inst->group; session->private_value = NULL; session->peer_scalar = NULL; session->my_scalar = NULL; session->k = NULL; session->my_element = NULL; session->peer_element = NULL; session->group = NULL; session->pwe = NULL; session->order = NULL; session->prime = NULL; /* * The admin can dynamically change the MTU. */ session->mtu = inst->fragment_size; vp = fr_pair_find_by_num(handler->request->packet->vps, PW_FRAMED_MTU, 0, TAG_ANY); /* * session->mtu is *our* MTU. We need to subtract off the EAP * overhead. * * 9 = 4 (EAPOL header) + 4 (EAP header) + 1 (EAP type) * * The fragmentation code deals with the included length * so we don't need to subtract that here. */ if (vp && (vp->vp_integer > 100) && (vp->vp_integer < session->mtu)) { session->mtu = vp->vp_integer - 9; } session->state = PWD_STATE_ID_REQ; session->in = NULL; session->out_pos = 0; handler->opaque = session; /* * construct an EAP-pwd-ID/Request */ session->out_len = sizeof(pwd_id_packet_t) + strlen(inst->server_id); if ((session->out = talloc_zero_array(session, uint8_t, session->out_len)) == NULL) { return 0; } packet = (pwd_id_packet_t *)session->out; packet->group_num = htons(session->group_num); packet->random_function = EAP_PWD_DEF_RAND_FUN; packet->prf = EAP_PWD_DEF_PRF; session->token = fr_rand(); memcpy(packet->token, (char *)&session->token, 4); packet->prep = EAP_PWD_PREP_NONE; memcpy(packet->identity, inst->server_id, session->out_len - sizeof(pwd_id_packet_t) ); handler->stage = PROCESS; return send_pwd_request(session, handler->eap_ds); }
static int generate_sql_clients(rlm_sql_t *inst) { rlm_sql_handle_t *handle; rlm_sql_row_t row; char querystr[MAX_QUERY_LEN]; RADCLIENT *c; char *prefix_ptr = NULL; unsigned int i = 0; int numf = 0; DEBUG("rlm_sql (%s): Processing generate_sql_clients", inst->config->xlat_name); /* NAS query isn't xlat'ed */ strlcpy(querystr, inst->config->nas_query, sizeof(querystr)); DEBUG("rlm_sql (%s) in generate_sql_clients: query is %s", inst->config->xlat_name, querystr); handle = sql_get_socket(inst); if (handle == NULL) return -1; if (rlm_sql_select_query(&handle,inst,querystr)){ return -1; } while(rlm_sql_fetch_row(&handle, inst) == 0) { i++; row = handle->row; if (row == NULL) break; /* * The return data for each row MUST be in the following order: * * 0. Row ID (currently unused) * 1. Name (or IP address) * 2. Shortname * 3. Type * 4. Secret * 5. Virtual Server (optional) */ if (!row[0]){ radlog(L_ERR, "rlm_sql (%s): No row id found on pass %d",inst->config->xlat_name,i); continue; } if (!row[1]){ radlog(L_ERR, "rlm_sql (%s): No nasname found for row %s",inst->config->xlat_name,row[0]); continue; } if (!row[2]){ radlog(L_ERR, "rlm_sql (%s): No short name found for row %s",inst->config->xlat_name,row[0]); continue; } if (!row[4]){ radlog(L_ERR, "rlm_sql (%s): No secret found for row %s",inst->config->xlat_name,row[0]); continue; } DEBUG("rlm_sql (%s): Read entry nasname=%s,shortname=%s,secret=%s",inst->config->xlat_name, row[1],row[2],row[4]); c = talloc_zero(inst, RADCLIENT); #ifdef WITH_DYNAMIC_CLIENTS c->dynamic = 1; #endif /* * Look for prefixes */ c->prefix = -1; prefix_ptr = strchr(row[1], '/'); if (prefix_ptr) { c->prefix = atoi(prefix_ptr + 1); if ((c->prefix < 0) || (c->prefix > 128)) { radlog(L_ERR, "rlm_sql (%s): Invalid Prefix value '%s' for IP.", inst->config->xlat_name, prefix_ptr + 1); talloc_free(c); continue; } /* Replace '/' with '\0' */ *prefix_ptr = '\0'; } /* * Always get the numeric representation of IP */ if (ip_hton(row[1], AF_UNSPEC, &c->ipaddr) < 0) { radlog(L_ERR, "rlm_sql (%s): Failed to look up hostname %s: %s", inst->config->xlat_name, row[1], fr_strerror()); talloc_free(c); continue; } else { char buffer[256]; ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)); c->longname = talloc_strdup(c, buffer); } if (c->prefix < 0) switch (c->ipaddr.af) { case AF_INET: c->prefix = 32; break; case AF_INET6: c->prefix = 128; break; default: break; } /* * Other values (secret, shortname, nastype, virtual_server) */ c->secret = talloc_strdup(c, row[4]); c->shortname = talloc_strdup(c, row[2]); if(row[3] != NULL) c->nastype = strdup(row[3]); numf = (inst->module->sql_num_fields)(handle, inst->config); if ((numf > 5) && (row[5] != NULL) && *row[5]) c->server = strdup(row[5]); DEBUG("rlm_sql (%s): Adding client %s (%s, server=%s) to clients list", inst->config->xlat_name, c->longname,c->shortname, c->server ? c->server : "<none>"); if (!client_add(NULL, c)) { sql_release_socket(inst, handle); DEBUG("rlm_sql (%s): Failed to add client %s (%s) to clients list. Maybe there's a duplicate?", inst->config->xlat_name, c->longname,c->shortname); client_free(c); return -1; } } (inst->module->sql_finish_select_query)(handle, inst->config); sql_release_socket(inst, handle); return 0; }
/* * Read config files. * * This function can ONLY be called from the main server process. */ int main_config_init(void) { char const *p = NULL; CONF_SECTION *cs; struct stat statbuf; cached_config_t *cc; char buffer[1024]; if (stat(radius_dir, &statbuf) < 0) { ERROR("Errors reading %s: %s", radius_dir, fr_syserror(errno)); return -1; } #ifdef S_IWOTH if ((statbuf.st_mode & S_IWOTH) != 0) { ERROR("Configuration directory %s is globally writable. Refusing to start due to insecure configuration.", radius_dir); return -1; } #endif #ifdef S_IROTH if (0 && (statbuf.st_mode & S_IROTH) != 0) { ERROR("Configuration directory %s is globally readable. Refusing to start due to insecure configuration.", radius_dir); return -1; } #endif INFO("Starting - reading configuration files ..."); /* * We need to load the dictionaries before reading the * configuration files. This is because of the * pre-compilation in conffile.c. That should probably * be fixed to be done as a second stage. */ if (!main_config.dictionary_dir) { main_config.dictionary_dir = talloc_typed_strdup(NULL, DICTDIR); } /* * Read the distribution dictionaries first, then * the ones in raddb. */ DEBUG2("including dictionary file %s/%s", main_config.dictionary_dir, RADIUS_DICTIONARY); if (dict_init(main_config.dictionary_dir, RADIUS_DICTIONARY) != 0) { ERROR("Errors reading dictionary: %s", fr_strerror()); return -1; } #define DICT_READ_OPTIONAL(_d, _n) \ do {\ switch (dict_read(_d, _n)) {\ case -1:\ ERROR("Errors reading %s/%s: %s", _d, _n, fr_strerror());\ return -1;\ case 0:\ DEBUG2("including dictionary file %s/%s", _d,_n);\ break;\ default:\ break;\ }\ } while (0) /* * Try to load protocol-specific dictionaries. It's OK * if they don't exist. */ #ifdef WITH_DHCP DICT_READ_OPTIONAL(main_config.dictionary_dir, "dictionary.dhcp"); #endif #ifdef WITH_VMPS DICT_READ_OPTIONAL(main_config.dictionary_dir, "dictionary.vqp"); #endif /* * It's OK if this one doesn't exist. */ DICT_READ_OPTIONAL(radius_dir, RADIUS_DICTIONARY); /* Read the configuration file */ snprintf(buffer, sizeof(buffer), "%.200s/%.50s.conf", radius_dir, main_config.name); if ((cs = cf_file_read(buffer)) == NULL) { ERROR("Errors reading or parsing %s", buffer); return -1; } /* * If there was no log destination set on the command line, * set it now. */ if (default_log.dst == L_DST_NULL) { if (cf_section_parse(cs, NULL, serverdest_config) < 0) { fprintf(stderr, "radiusd: Error: Failed to parse log{} section.\n"); cf_file_free(cs); return -1; } if (!radlog_dest) { fprintf(stderr, "radiusd: Error: No log destination specified.\n"); cf_file_free(cs); return -1; } default_log.dst = fr_str2int(log_str2dst, radlog_dest, L_DST_NUM_DEST); if (default_log.dst == L_DST_NUM_DEST) { fprintf(stderr, "radiusd: Error: Unknown log_destination %s\n", radlog_dest); cf_file_free(cs); return -1; } if (default_log.dst == L_DST_SYSLOG) { /* * Make sure syslog_facility isn't NULL * before using it */ if (!syslog_facility) { fprintf(stderr, "radiusd: Error: Syslog chosen but no facility was specified\n"); cf_file_free(cs); return -1; } main_config.syslog_facility = fr_str2int(syslog_str2fac, syslog_facility, -1); if (main_config.syslog_facility < 0) { fprintf(stderr, "radiusd: Error: Unknown syslog_facility %s\n", syslog_facility); cf_file_free(cs); return -1; } #ifdef HAVE_SYSLOG_H /* * Call openlog only once, when the * program starts. */ openlog(progname, LOG_PID, main_config.syslog_facility); #endif } else if (default_log.dst == L_DST_FILES) { if (!main_config.log_file) { fprintf(stderr, "radiusd: Error: Specified \"files\" as a log destination, but no log filename was given!\n"); cf_file_free(cs); return -1; } } } #ifdef HAVE_SETUID /* * Switch users as early as possible. */ if (!switch_users(cs)) fr_exit(1); #endif /* * Open the log file AFTER switching uid / gid. If we * did switch uid/gid, then the code in switch_users() * took care of setting the file permissions correctly. */ if ((default_log.dst == L_DST_FILES) && (default_log.fd < 0)) { default_log.fd = open(main_config.log_file, O_WRONLY | O_APPEND | O_CREAT, 0640); if (default_log.fd < 0) { fprintf(stderr, "radiusd: Failed to open log file %s: %s\n", main_config.log_file, fr_syserror(errno)); cf_file_free(cs); return -1; } } /* * This allows us to figure out where, relative to * radiusd.conf, the other configuration files exist. */ if (cf_section_parse(cs, NULL, server_config) < 0) { return -1; } /* * We ignore colourization of output until after the * configuration files have been parsed. */ p = getenv("TERM"); if (do_colourise && p && isatty(default_log.fd) && strstr(p, "xterm")) { default_log.colourise = true; } else { default_log.colourise = false; } /* * Starting the server, WITHOUT "-x" on the * command-line: use whatever is in the config * file. */ if (debug_flag == 0) { debug_flag = main_config.debug_level; } fr_debug_flag = debug_flag; FR_INTEGER_COND_CHECK("max_request_time", main_config.max_request_time, (main_config.max_request_time != 0), 100); FR_INTEGER_BOUND_CHECK("reject_delay", main_config.reject_delay, <=, 10); FR_INTEGER_BOUND_CHECK("cleanup_delay", main_config.cleanup_delay, <=, 10); /* * Set default initial request processing delay to 1/3 of a second. * Will be updated by the lowest response window across all home servers, * if it is less than this. */ main_config.init_delay.tv_sec = 0; main_config.init_delay.tv_usec = 1000000 / 3; /* * Free the old configuration items, and replace them * with the new ones. * * Note that where possible, we do atomic switch-overs, * to ensure that the pointers are always valid. */ rad_assert(main_config.config == NULL); root_config = main_config.config = cs; DEBUG2("%s: #### Loading Realms and Home Servers ####", main_config.name); if (!realms_init(cs)) { return -1; } DEBUG2("%s: #### Loading Clients ####", main_config.name); if (!clients_parse_section(cs, false)) { return -1; } /* * Register the %{config:section.subsection} xlat function. */ xlat_register("config", xlat_config, NULL, NULL); xlat_register("client", xlat_client, NULL, NULL); xlat_register("getclient", xlat_getclient, NULL, NULL); /* * Go update our behaviour, based on the configuration * changes. */ /* * Sanity check the configuration for internal * consistency. */ FR_INTEGER_BOUND_CHECK("reject_delay", main_config.reject_delay, <=, main_config.cleanup_delay); if (chroot_dir) { if (chdir(radlog_dir) < 0) { ERROR("Failed to 'chdir %s' after chroot: %s", radlog_dir, fr_syserror(errno)); return -1; } } cc = talloc_zero(NULL, cached_config_t); if (!cc) return -1; cc->cs = talloc_steal(cc ,cs); rad_assert(cs_cache == NULL); cs_cache = cc; /* Clear any unprocessed configuration errors */ (void) fr_strerror(); return 0; }
/** Extract useful information from the rootDSE of the LDAP server * * @param[in] ctx to allocate fr_ldap_directory_t in. * @param[out] out where to write pointer to new fr_ldap_directory_t struct. * @param[in,out] pconn connection for querying the directory. * @return * - 0 on success. * - 1 if we failed identifying the directory server. * - -1 on error. */ int fr_ldap_directory_alloc(TALLOC_CTX *ctx, fr_ldap_directory_t **out, fr_ldap_connection_t **pconn) { static char const *attrs[] = { "vendorname", "vendorversion", "isGlobalCatalogReady", "objectClass", "orcldirectoryversion", NULL }; fr_ldap_rcode_t status; int entry_cnt; int ldap_errno; int i, num; int rcode = 0; struct berval **values = NULL; fr_ldap_directory_t *directory; LDAPMessage *result = NULL, *entry; *out = NULL; directory = talloc_zero(ctx, fr_ldap_directory_t); if (!directory) return -2; *out = directory; directory->type = FR_LDAP_DIRECTORY_UNKNOWN; status = fr_ldap_search(&result, NULL, pconn, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, NULL, NULL); switch (status) { case LDAP_PROC_SUCCESS: break; case LDAP_PROC_NO_RESULT: WARN("Capability check failed: Can't access rootDSE"); rcode = 1; goto finish; default: rcode = 1; goto finish; } entry_cnt = ldap_count_entries((*pconn)->handle, result); if (entry_cnt != 1) { WARN("Capability check failed: Ambiguous result for rootDSE, expected 1 entry, got %i", entry_cnt); rcode = 1; goto finish; } entry = ldap_first_entry((*pconn)->handle, result); if (!entry) { ldap_get_option((*pconn)->handle, LDAP_OPT_RESULT_CODE, &ldap_errno); WARN("Capability check failed: Failed retrieving entry: %s", ldap_err2string(ldap_errno)); rcode = 1; goto finish; } values = ldap_get_values_len((*pconn)->handle, entry, "vendorname"); if (values) { directory->vendor_str = fr_ldap_berval_to_string(directory, values[0]); INFO("Directory vendor: %s", directory->vendor_str); ldap_value_free_len(values); } values = ldap_get_values_len((*pconn)->handle, entry, "vendorversion"); if (values) { directory->version_str = fr_ldap_berval_to_string(directory, values[0]); INFO("Directory version: %s", directory->version_str); ldap_value_free_len(values); } if (directory->vendor_str) { if (strcasestr(directory->vendor_str, "International Business Machines")) { directory->type = FR_LDAP_DIRECTORY_EDIRECTORY; } goto found; } if (directory->version_str) { /* * Novell eDirectory vendorversion contains eDirectory */ if (strcasestr(directory->version_str, "eDirectory")) { directory->type = FR_LDAP_DIRECTORY_EDIRECTORY; /* * Oracle unified directory vendorversion contains Oracle Unified Directory */ } else if (strcasestr(directory->version_str, "Oracle Unified Directory")) { directory->type = FR_LDAP_DIRECTORY_ORACLE_UNIFIED_DIRECTORY; /* * Unbound directory vendorversion contains UnboundID */ } else if (strcasestr(directory->version_str, "UnboundID")) { directory->type = FR_LDAP_DIRECTORY_UNBOUND_ID; /* * NetScape directory venderversion contains Netscape-Directory */ } else if (strcasestr(directory->version_str, "Netscape-Directory")) { directory->type = FR_LDAP_DIRECTORY_NETSCAPE; /* * Siemens AG directory vendorversion contains DirX Directory */ } else if (strcasestr(directory->version_str, "DirX Directory")) { directory->type = FR_LDAP_DIRECTORY_SIEMENS_AG; /* * Sun One Directory vendorversion contains Sun Java */ } else if (strcasestr(directory->version_str, "Sun Java")) { directory->type = FR_LDAP_DIRECTORY_SUN_ONE_DIRECTORY; } goto found; } /* * isGlobalCatalogReady is only present on ActiveDirectory * instances. AD doesn't provide vendorname or vendorversion */ values = ldap_get_values_len((*pconn)->handle, entry, "isGlobalCatalogReady"); if (values) { directory->type = FR_LDAP_DIRECTORY_ACTIVE_DIRECTORY; ldap_value_free_len(values); goto found; } /* * OpenLDAP has a special objectClass for its RootDSE */ values = ldap_get_values_len((*pconn)->handle, entry, "objectClass"); if (values) { num = ldap_count_values_len(values); for (i = 0; i < num; i++) { if (strncmp("OpenLDAProotDSE", values[i]->bv_val, values[i]->bv_len) == 0) { directory->type = FR_LDAP_DIRECTORY_OPENLDAP; } } ldap_value_free_len(values); goto found; } /* * Oracle Virtual Directory and Oracle Internet Directory */ values = ldap_get_values_len((*pconn)->handle, entry, "orcldirectoryversion"); if (values) { if (memmem(values[0]->bv_val, values[0]->bv_len, "OID", 3)) { directory->type = FR_LDAP_DIRECTORY_ORACLE_INTERNET_DIRECTORY; } else if (memmem(values[0]->bv_val, values[0]->bv_len, "OVD", 3)) { directory->type = FR_LDAP_DIRECTORY_ORACLE_VIRTUAL_DIRECTORY; } ldap_value_free_len(values); } found: INFO("Directory type: %s", fr_int2str(fr_ldap_directory_type_table, directory->type, "<INVALID>")); switch (directory->type) { case FR_LDAP_DIRECTORY_ACTIVE_DIRECTORY: case FR_LDAP_DIRECTORY_EDIRECTORY: directory->cleartext_password = false; break; default: directory->cleartext_password = true; break; } finish: if (result) ldap_msgfree(result); return rcode; }
/************************************************************************* * * Function: sql_create_socket * * Purpose: Establish connection to the db * *************************************************************************/ static int sql_socket_init(rlm_sql_handle_t *handle, rlm_sql_config_t *config) { rlm_sql_mysql_conn_t *conn; unsigned long sql_flags; MEM(conn = handle->conn = talloc_zero(handle, rlm_sql_mysql_conn_t)); talloc_set_destructor((void *) conn, sql_socket_destructor); DEBUG("rlm_sql_mysql: Starting connect to MySQL server"); mysql_init(&(conn->db)); mysql_options(&(conn->db), MYSQL_READ_DEFAULT_GROUP, "freeradius"); #if (MYSQL_VERSION_ID >= 50000) if (config->query_timeout) { unsigned int timeout = config->query_timeout; /* * 3 retries are hard-coded into the MySQL library. * We ensure that the REAL timeout is what the user * set by accounting for that. */ if (timeout > 3) timeout /= 3; mysql_options(&(conn->db), MYSQL_OPT_CONNECT_TIMEOUT, &timeout); mysql_options(&(conn->db), MYSQL_OPT_READ_TIMEOUT, &timeout); mysql_options(&(conn->db), MYSQL_OPT_WRITE_TIMEOUT, &timeout); } #endif #if (MYSQL_VERSION_ID >= 40100) sql_flags = CLIENT_MULTI_RESULTS | CLIENT_FOUND_ROWS; #else sql_flags = CLIENT_FOUND_ROWS; #endif #ifdef CLIENT_MULTI_STATEMENTS sql_flags |= CLIENT_MULTI_STATEMENTS; #endif conn->sock = mysql_real_connect(&(conn->db), config->sql_server, config->sql_login, config->sql_password, config->sql_db, atoi(config->sql_port), NULL, sql_flags); if (!conn->sock) { radlog(L_ERR, "rlm_sql_mysql: Couldn't connect socket to MySQL " "server %s@%s:%s", config->sql_login, config->sql_server, config->sql_db); radlog(L_ERR, "rlm_sql_mysql: Mysql error '%s'", mysql_error(&conn->db)); conn->sock = NULL; return -1; } return 0; }
/** Create and insert a cache entry * * @return * - #RLM_MODULE_OK on success. * - #RLM_MODULE_UPDATED if we merged the cache entry. * - #RLM_MODULE_FAIL on failure. */ static rlm_rcode_t cache_insert(rlm_cache_t const *inst, REQUEST *request, rlm_cache_handle_t **handle, uint8_t const *key, size_t key_len, int ttl) { vp_map_t const *map; vp_map_t **last, *c_map; VALUE_PAIR *vp; bool merge = false; rlm_cache_entry_t *c; size_t len; TALLOC_CTX *pool; if ((inst->config.max_entries > 0) && inst->driver->count && (inst->driver->count(&inst->config, inst->driver_inst->data, request, handle) > inst->config.max_entries)) { RWDEBUG("Cache is full: %d entries", inst->config.max_entries); return RLM_MODULE_FAIL; } c = cache_alloc(inst, request); if (!c) return RLM_MODULE_FAIL; c->key = talloc_memdup(c, key, key_len); c->key_len = key_len; c->created = c->expires = request->packet->timestamp.tv_sec; c->expires += ttl; last = &c->maps; RDEBUG2("Creating new cache entry"); /* * Alloc a pool so we don't have excessive allocs when * gathering VALUE_PAIRs to cache. */ pool = talloc_pool(NULL, 2048); for (map = inst->maps; map != NULL; map = map->next) { VALUE_PAIR *to_cache = NULL; fr_cursor_t cursor; rad_assert(map->lhs && map->rhs); /* * Calling map_to_vp gives us exactly the same result, * as if this were an update section. */ if (map_to_vp(pool, &to_cache, request, map, NULL) < 0) { RDEBUG2("Skipping %s", map->rhs->name); continue; } for (vp = fr_cursor_init(&cursor, &to_cache); vp; vp = fr_cursor_next(&cursor)) { /* * Prevent people from accidentally caching * cache control attributes. */ if (map->rhs->type == TMPL_TYPE_LIST) switch (vp->da->attr) { case FR_CACHE_TTL: case FR_CACHE_STATUS_ONLY: case FR_CACHE_MERGE_NEW: case FR_CACHE_ENTRY_HITS: RDEBUG2("Skipping %s", vp->da->name); continue; default: break; } RINDENT(); if (RDEBUG_ENABLED2) map_debug_log(request, map, vp); REXDENT(); MEM(c_map = talloc_zero(c, vp_map_t)); c_map->op = map->op; /* * Now we turn the VALUE_PAIRs into maps. */ switch (map->lhs->type) { /* * Attributes are easy, reuse the LHS, and create a new * RHS with the fr_value_box_t from the VALUE_PAIR. */ case TMPL_TYPE_ATTR: c_map->lhs = map->lhs; /* lhs shouldn't be touched, so this is ok */ do_rhs: MEM(c_map->rhs = tmpl_init(talloc(c_map, vp_tmpl_t), TMPL_TYPE_DATA, map->rhs->name, map->rhs->len, T_BARE_WORD)); if (fr_value_box_copy(c_map->rhs, &c_map->rhs->tmpl_value, &vp->data) < 0) { REDEBUG("Failed copying attribute value"); error: talloc_free(pool); talloc_free(c); return RLM_MODULE_FAIL; } c_map->rhs->tmpl_value_type = vp->vp_type; if (vp->vp_type == FR_TYPE_STRING) { c_map->rhs->quote = is_printable(vp->vp_strvalue, vp->vp_length) ? T_SINGLE_QUOTED_STRING : T_DOUBLE_QUOTED_STRING; } break; /* * Lists are weird... We need to fudge a new LHS template, * which is a combination of the LHS list and the attribute. */ case TMPL_TYPE_LIST: { char attr[256]; MEM(c_map->lhs = tmpl_init(talloc(c_map, vp_tmpl_t), TMPL_TYPE_ATTR, map->lhs->name, map->lhs->len, T_BARE_WORD)); c_map->lhs->tmpl_da = vp->da; if (vp->da->flags.is_unknown) { /* for tmpl_verify() */ c_map->lhs->tmpl_unknown = fr_dict_unknown_acopy(c_map->lhs, vp->da); c_map->lhs->tmpl_da = c_map->lhs->tmpl_unknown; } c_map->lhs->tmpl_tag = vp->tag; c_map->lhs->tmpl_list = map->lhs->tmpl_list; c_map->lhs->tmpl_num = map->lhs->tmpl_num; c_map->lhs->tmpl_request = map->lhs->tmpl_request; /* * We need to rebuild the attribute name, to be the * one we copied from the source list. */ len = tmpl_snprint(attr, sizeof(attr), c_map->lhs); if (is_truncated(len, sizeof(attr))) { REDEBUG("Serialized attribute too long. Must be < " STRINGIFY(sizeof(attr)) " bytes, got %zu bytes", len); goto error; } c_map->lhs->len = len; c_map->lhs->name = talloc_typed_strdup(c_map->lhs, attr); } goto do_rhs; default: rad_assert(0); } *last = c_map; last = &(*last)->next; } talloc_free_children(pool); /* reset pool state */ } talloc_free(pool); /* * Check to see if we need to merge the entry into the request */ vp = fr_pair_find_by_da(request->control, attr_cache_merge_new, TAG_ANY); if (vp && vp->vp_bool) merge = true; if (merge) cache_merge(inst, request, c); for (;;) { cache_status_t ret; ret = inst->driver->insert(&inst->config, inst->driver_inst->data, request, *handle, c); switch (ret) { case CACHE_RECONNECT: if (cache_reconnect(handle, inst, request) == 0) continue; return RLM_MODULE_FAIL; case CACHE_OK: RDEBUG2("Committed entry, TTL %d seconds", ttl); cache_free(inst, &c); return merge ? RLM_MODULE_UPDATED : RLM_MODULE_OK; default: talloc_free(c); /* Failed insertion - use talloc_free not the driver free */ return RLM_MODULE_FAIL; } } }
/** Allocate a cache entry * * This is used so that drivers may use their own allocation functions * to allocate structures larger than the normal rlm_cache_entry_t. * * If the driver doesn't specify a custom allocation function, the cache * entry is talloced in the NULL ctx. */ static rlm_cache_entry_t *cache_alloc(rlm_cache_t const *inst, REQUEST *request) { if (inst->driver->alloc) return inst->driver->alloc(&inst->config, inst->driver_inst->data, request); return talloc_zero(NULL, rlm_cache_entry_t); }
/* * Find a module instance. */ module_instance_t *find_module_instance(CONF_SECTION *modules, char const *askedname, int do_link) { int check_config_safe = false; CONF_SECTION *cs; char const *name1, *instname; module_instance_t *node, myNode; char module_name[256]; if (!modules) return NULL; /* * Look for the real name. Ignore the first character, * which tells the server "it's OK for this module to not * exist." */ instname = askedname; if (instname[0] == '-') { instname++; } /* * Module instances are declared in the modules{} block * and referenced later by their name, which is the * name2 from the config section, or name1 if there was * no name2. */ cs = cf_section_sub_find_name2(modules, NULL, instname); if (!cs) { ERROR("Cannot find a configuration entry for module \"%s\"", instname); return NULL; } /* * If there's already a module instance, return it. */ strlcpy(myNode.name, instname, sizeof(myNode.name)); node = rbtree_finddata(instance_tree, &myNode); if (node) { return node; } if (!do_link) { return NULL; } name1 = cf_section_name1(cs); /* * Found the configuration entry, hang the node struct off of the * configuration section. If the CS is free'd the instance will * be too. */ node = talloc_zero(cs, module_instance_t); node->cs = cs; /* * Names in the "modules" section aren't prefixed * with "rlm_", so we add it here. */ snprintf(module_name, sizeof(module_name), "rlm_%s", name1); /* * Pull in the module object */ node->entry = linkto_module(module_name, cs); if (!node->entry) { talloc_free(node); /* linkto_module logs any errors */ return NULL; } if (check_config && (node->entry->module->instantiate) && (node->entry->module->type & RLM_TYPE_CHECK_CONFIG_SAFE) == 0) { char const *value = NULL; CONF_PAIR *cp; cp = cf_pair_find(cs, "force_check_config"); if (cp) { value = cf_pair_value(cp); } if (value && (strcmp(value, "yes") == 0)) goto print_inst; cf_log_module(cs, "Skipping instantiation of %s", instname); } else { print_inst: check_config_safe = true; cf_log_module(cs, "Instantiating module \"%s\" from file %s", instname, cf_section_filename(cs)); } strlcpy(node->name, instname, sizeof(node->name)); /* * Parse the module configuration, and setup destructors so the * module's detach method is called when it's instance data is * about to be freed. */ if (module_conf_parse(node, &node->insthandle) < 0) { talloc_free(node); return NULL; } /* * Call the module's instantiation routine. */ if ((node->entry->module->instantiate) && (!check_config || check_config_safe) && ((node->entry->module->instantiate)(cs, node->insthandle) < 0)) { cf_log_err_cs(cs, "Instantiation failed for module \"%s\"", node->name); talloc_free(node); return NULL; } #ifdef HAVE_PTHREAD_H /* * If we're threaded, check if the module is thread-safe. * * If it isn't, we create a mutex. */ if ((node->entry->module->type & RLM_TYPE_THREAD_UNSAFE) != 0) { node->mutex = talloc_zero(node, pthread_mutex_t); /* * Initialize the mutex. */ pthread_mutex_init(node->mutex, NULL); } else { /* * The module is thread-safe. Don't give it a mutex. */ node->mutex = NULL; } #endif rbtree_insert(instance_tree, node); return node; }
static int rlm_sql_instantiate(CONF_SECTION *conf, void **instance) { rlm_sql_t *inst; const char *xlat_name; *instance = inst = talloc_zero(conf, rlm_sql_t); if (!inst) return -1; /* * Cache the SQL-User-Name DICT_ATTR, so we can be slightly * more efficient about creating SQL-User-Name attributes. */ inst->sql_user = dict_attrbyname("SQL-User-Name"); if (!inst->sql_user) { return -1; } /* * Export these methods, too. This avoids RTDL_GLOBAL. */ inst->sql_set_user = sql_set_user; inst->sql_get_socket = sql_get_socket; inst->sql_release_socket = sql_release_socket; inst->sql_escape_func = sql_escape_func; inst->sql_query = rlm_sql_query; inst->sql_select_query = rlm_sql_select_query; inst->sql_fetch_row = rlm_sql_fetch_row; inst->config = talloc_zero(inst, rlm_sql_config_t); inst->cs = conf; xlat_name = cf_section_name2(conf); if (xlat_name == NULL) { xlat_name = cf_section_name1(conf); } else { char *group_name; const DICT_ATTR *dattr; ATTR_FLAGS flags; /* * Allocate room for <instance>-SQL-Group */ group_name = talloc_asprintf(inst, "%s-SQL-Group", xlat_name); DEBUG("rlm_sql (%s): Creating new attribute %s", xlat_name, group_name); memset(&flags, 0, sizeof(flags)); if (dict_addattr(group_name, -1, 0, PW_TYPE_STRING, flags) < 0) { radlog(L_ERR, "rlm_sql (%s): Failed to create " "attribute %s: %s", xlat_name, group_name, fr_strerror()); return -1; } dattr = dict_attrbyname(group_name); if (!dattr) { radlog(L_ERR, "rlm_sql (%s): Failed to create " "attribute %s", xlat_name, group_name); return -1; } if (inst->config->groupmemb_query && inst->config->groupmemb_query[0]) { DEBUG("rlm_sql (%s): Registering sql_groupcmp for %s", xlat_name, group_name); paircompare_register(dattr->attr, PW_USER_NAME, sql_groupcmp, inst); } } rad_assert(xlat_name); /* * Register the SQL xlat function */ inst->config->xlat_name = talloc_strdup(inst->config, xlat_name); xlat_register(xlat_name, sql_xlat, inst); /* * If the configuration parameters can't be parsed, then fail. */ if ((cf_section_parse(conf, inst->config, module_config) < 0) || (parse_sub_section(conf, inst, &inst->config->accounting, RLM_COMPONENT_ACCT) < 0) || (parse_sub_section(conf, inst, &inst->config->postauth, RLM_COMPONENT_POST_AUTH) < 0)) { radlog(L_ERR, "rlm_sql (%s): Failed parsing configuration", inst->config->xlat_name); return -1; } /* * Sanity check for crazy people. */ if (strncmp(inst->config->sql_driver_name, "rlm_sql_", 8) != 0) { radlog(L_ERR, "rlm_sql (%s): \"%s\" is NOT an SQL driver!", inst->config->xlat_name, inst->config->sql_driver_name); return -1; } /* * Load the appropriate driver for our database */ inst->handle = lt_dlopenext(inst->config->sql_driver_name); if (inst->handle == NULL) { radlog(L_ERR, "Could not link driver %s: %s", inst->config->sql_driver_name, lt_dlerror()); radlog(L_ERR, "Make sure it (and all its dependent libraries!)" "are in the search path of your system's ld."); return -1; } inst->module = (rlm_sql_module_t *) lt_dlsym(inst->handle, inst->config->sql_driver_name); if (!inst->module) { radlog(L_ERR, "Could not link symbol %s: %s", inst->config->sql_driver_name, lt_dlerror()); return -1; } if (inst->module->sql_instantiate) { CONF_SECTION *cs; const char *name; name = strrchr(inst->config->sql_driver_name, '_'); if (!name) { name = inst->config->sql_driver_name; } else { name++; } cs = cf_section_sub_find(conf, name); if (!cs) { cs = cf_section_alloc(conf, name, NULL); if (!cs) { return -1; } } /* * It's up to the driver to register a destructor */ if (inst->module->sql_instantiate(cs, inst->config) < 0) { return -1; } } radlog(L_INFO, "rlm_sql (%s): Driver %s (module %s) loaded and linked", inst->config->xlat_name, inst->config->sql_driver_name, inst->module->name); /* * Initialise the connection pool for this instance */ radlog(L_INFO, "rlm_sql (%s): Attempting to connect to database \"%s\"", inst->config->xlat_name, inst->config->sql_db); if (sql_socket_pool_init(inst) < 0) return -1; if (inst->config->groupmemb_query && inst->config->groupmemb_query[0]) { paircompare_register(PW_SQL_GROUP, PW_USER_NAME, sql_groupcmp, inst); } if (inst->config->do_clients) { if (generate_sql_clients(inst) == -1){ radlog(L_ERR, "Failed to load clients from SQL."); return -1; } } return RLM_MODULE_OK; }
int main(int argc, char **argv) { int c; char filesecret[256]; FILE *fp; int force_af = AF_UNSPEC; radsnmp_conf_t *conf; int ret; int sockfd; TALLOC_CTX *autofree = talloc_autofree_context(); fr_log_fp = stderr; conf = talloc_zero(autofree, radsnmp_conf_t); conf->proto = IPPROTO_UDP; conf->dict_dir = DICTDIR; conf->raddb_dir = RADDBDIR; conf->secret = talloc_strdup(conf, "testing123"); conf->timeout.tv_sec = 3; conf->retries = 5; #ifndef NDEBUG if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) { fr_perror("radsnmp"); exit(EXIT_FAILURE); } #endif talloc_set_log_stderr(); while ((c = getopt(argc, argv, "46c:d:D:f:Fhi:l:n:p:P:qr:sS:t:vx")) != -1) switch (c) { case '4': force_af = AF_INET; break; case '6': force_af = AF_INET6; break; case 'D': conf->dict_dir = optarg; break; case 'd': conf->raddb_dir = optarg; break; case 'l': { int log_fd; if (strcmp(optarg, "stderr") == 0) { fr_log_fp = stderr; /* stdout goes to netsnmp */ break; } log_fd = open(optarg, O_WRONLY | O_APPEND | O_CREAT, 0640); if (log_fd < 0) { fprintf(stderr, "radsnmp: Failed to open log file %s: %s\n", optarg, fr_syserror(errno)); exit(EXIT_FAILURE); } fr_log_fp = fdopen(log_fd, "a"); } break; case 'P': conf->proto_str = optarg; if (strcmp(conf->proto_str, "tcp") != 0) { if (strcmp(conf->proto_str, "udp") != 0) usage(); } else { conf->proto = IPPROTO_TCP; } break; case 'r': if (!isdigit((int) *optarg)) usage(); conf->retries = atoi(optarg); if ((conf->retries == 0) || (conf->retries > 1000)) usage(); break; case 'S': { char *p; fp = fopen(optarg, "r"); if (!fp) { ERROR("Error opening %s: %s", optarg, fr_syserror(errno)); exit(EXIT_FAILURE); } if (fgets(filesecret, sizeof(filesecret), fp) == NULL) { ERROR("Error reading %s: %s", optarg, fr_syserror(errno)); exit(EXIT_FAILURE); } fclose(fp); /* truncate newline */ p = filesecret + strlen(filesecret) - 1; while ((p >= filesecret) && (*p < ' ')) { *p = '\0'; --p; } if (strlen(filesecret) < 2) { ERROR("Secret in %s is too short", optarg); exit(EXIT_FAILURE); } talloc_free(conf->secret); conf->secret = talloc_strdup(conf, filesecret); } break; case 't': if (fr_timeval_from_str(&conf->timeout, optarg) < 0) { ERROR("Failed parsing timeout value %s", fr_strerror()); exit(EXIT_FAILURE); } break; case 'v': DEBUG("%s", radsnmp_version); exit(0); case 'x': fr_debug_lvl++; break; case 'h': default: usage(); } argc -= (optind - 1); argv += (optind - 1); if ((argc < 2) || ((conf->secret == NULL) && (argc < 3))) { ERROR("Insufficient arguments"); usage(); } /* * Mismatch between the binary and the libraries it depends on */ if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) { fr_perror("radsnmp"); return EXIT_FAILURE; } if (fr_dict_autoload(radsnmp_dict) < 0) { fr_perror("radsnmp"); exit(EXIT_FAILURE); } if (fr_dict_attr_autoload(radsnmp_dict_attr) < 0) { fr_perror("radsnmp"); exit(EXIT_FAILURE); } if (fr_dict_read(dict_freeradius, conf->raddb_dir, FR_DICTIONARY_FILE) == -1) { fr_perror("radsnmp"); exit(EXIT_FAILURE); } fr_strerror(); /* Clear the error buffer */ if (fr_log_fp) setvbuf(fr_log_fp, NULL, _IONBF, 0); /* * Get the request type */ if (!isdigit((int) argv[2][0])) { int code; code = fr_str2int(fr_request_types, argv[2], -1); if (code < 0) { ERROR("Unrecognised request type \"%s\"", argv[2]); usage(); } conf->code = (unsigned int)code; } else { conf->code = atoi(argv[2]); } /* * Resolve hostname. */ if (fr_inet_pton_port(&conf->server_ipaddr, &conf->server_port, argv[1], -1, force_af, true, true) < 0) { ERROR("%s", fr_strerror()); exit(EXIT_FAILURE); } /* * Add the secret */ if (argv[3]) { talloc_free(conf->secret); conf->secret = talloc_strdup(conf, argv[3]); } conf->snmp_root = fr_dict_attr_child_by_num(attr_vendor_specific, VENDORPEC_FREERADIUS); if (!conf->snmp_root) { ERROR("Incomplete dictionary: Missing definition for Extended-Attribute-1(%i)." "Vendor-Specific(%i).FreeRADIUS(%i)", attr_extended_attribute_1->attr, attr_vendor_specific->attr, VENDORPEC_FREERADIUS); dict_error: talloc_free(conf); exit(EXIT_FAILURE); } conf->snmp_oid_root = fr_dict_attr_child_by_num(conf->snmp_root, 1); if (!conf->snmp_oid_root) { ERROR("Incomplete dictionary: Missing definition for 1.Extended-Attribute-1(%i)." "Vendor-Specific(%i).FreeRADIUS(%i).FreeRADIUS-Iso(%i)", attr_extended_attribute_1->attr, attr_vendor_specific->attr, VENDORPEC_FREERADIUS, 1); goto dict_error; } switch (conf->proto) { case IPPROTO_TCP: sockfd = fr_socket_client_tcp(NULL, &conf->server_ipaddr, conf->server_port, true); break; default: case IPPROTO_UDP: sockfd = fr_socket_client_udp(NULL, NULL, &conf->server_ipaddr, conf->server_port, true); break; } if (sockfd < 0) { ERROR("Failed connecting to server %s:%hu", "foo", conf->server_port); ret = 1; goto finish; } fr_set_signal(SIGPIPE, rs_signal_stop); fr_set_signal(SIGINT, rs_signal_stop); fr_set_signal(SIGTERM, rs_signal_stop); #ifdef SIGQUIT fr_set_signal(SIGQUIT, rs_signal_stop); #endif DEBUG("%s - Starting pass_persist read loop", radsnmp_version); ret = radsnmp_send_recv(conf, sockfd); DEBUG("Read loop done"); finish: if (fr_log_fp) fflush(fr_log_fp); /* * Everything should be parented from conf */ talloc_free(conf); /* * ...except the dictionaries */ fr_dict_autofree(radsnmp_dict); return ret; }
/** Allocate a new client from a config section * * @param ctx to allocate new clients in. * @param cs to process as a client. * @param in_server Whether the client should belong to a specific virtual server. * @param with_coa If true and coa_server or coa_pool aren't specified automatically, * create a coa home_server section and add it to the client CONF_SECTION. * @return new RADCLIENT struct. */ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, bool in_server, bool with_coa) { RADCLIENT *c; char const *name2; name2 = cf_section_name2(cs); if (!name2) { cf_log_err_cs(cs, "Missing client name"); return NULL; } /* * The size is fine.. Let's create the buffer */ c = talloc_zero(ctx, RADCLIENT); c->cs = cs; memset(&cl_ipaddr, 0, sizeof(cl_ipaddr)); if (cf_section_parse(cs, c, client_config) < 0) { cf_log_err_cs(cs, "Error parsing client section"); error: client_free(c); #ifdef WITH_TCP hs_proto = NULL; cl_srcipaddr = NULL; #endif return NULL; } /* * Global clients can set servers to use, per-server clients cannot. */ if (in_server && c->server) { cf_log_err_cs(cs, "Clients inside of an server section cannot point to a server"); goto error; } /* * Newer style client definitions with either ipaddr or ipaddr6 * config items. */ if (cf_pair_find(cs, "ipaddr") || cf_pair_find(cs, "ipv4addr") || cf_pair_find(cs, "ipv6addr")) { char buffer[128]; /* * Sets ipv4/ipv6 address and prefix. */ c->ipaddr = cl_ipaddr; /* * Set the long name to be the result of a reverse lookup on the IP address. */ ip_ntoh(&c->ipaddr, buffer, sizeof(buffer)); c->longname = talloc_typed_strdup(c, buffer); /* * Set the short name to the name2. */ if (!c->shortname) c->shortname = talloc_typed_strdup(c, name2); /* * No "ipaddr" or "ipv6addr", use old-style "client <ipaddr> {" syntax. */ } else { cf_log_err_cs(cs, "No 'ipaddr' or 'ipv4addr' or 'ipv6addr' configuration " "directive found in client %s", name2); goto error; } c->proto = IPPROTO_UDP; if (hs_proto) { if (strcmp(hs_proto, "udp") == 0) { hs_proto = NULL; #ifdef WITH_TCP } else if (strcmp(hs_proto, "tcp") == 0) { hs_proto = NULL; c->proto = IPPROTO_TCP; # ifdef WITH_TLS } else if (strcmp(hs_proto, "tls") == 0) { hs_proto = NULL; c->proto = IPPROTO_TCP; c->tls_required = true; } else if (strcmp(hs_proto, "radsec") == 0) { hs_proto = NULL; c->proto = IPPROTO_TCP; c->tls_required = true; # endif } else if (strcmp(hs_proto, "*") == 0) { hs_proto = NULL; c->proto = IPPROTO_IP; /* fake for dual */ #endif } else { cf_log_err_cs(cs, "Unknown proto \"%s\".", hs_proto); goto error; } } /* * If a src_ipaddr is specified, when we send the return packet * we will use this address instead of the src from the * request. */ if (cl_srcipaddr) { #ifdef WITH_UDPFROMTO switch (c->ipaddr.af) { case AF_INET: if (fr_pton4(&c->src_ipaddr, cl_srcipaddr, -1, true, false) < 0) { cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror()); goto error; } break; case AF_INET6: if (fr_pton6(&c->src_ipaddr, cl_srcipaddr, -1, true, false) < 0) { cf_log_err_cs(cs, "Failed parsing src_ipaddr: %s", fr_strerror()); goto error; } break; default: rad_assert(0); } #else WARN("Server not built with udpfromto, ignoring client src_ipaddr"); #endif cl_srcipaddr = NULL; } /* * A response_window of zero is OK, and means that it's * ignored by the rest of the server timers. */ if (timerisset(&c->response_window)) { FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, >=, 0, 1000); FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, 60, 0); FR_TIMEVAL_BOUND_CHECK("response_window", &c->response_window, <=, main_config.max_request_time, 0); }
/** \details Retrieve the message properties for an already open message. This function is very similar to OpenMessage, but works on an already open message object. \param obj_message the message object to retrieve the properties for. \return MAPI_E_SUCCESS on success, otherwise MAPI error. \note Developers may also call GetLastError() to retrieve the last MAPI error code. Possible MAPI error codes are: - MAPI_E_NOT_INITIALIZED: MAPI subsystem has not been initialized - MAPI_E_INVALID_PARAMETER: obj_store is undefined - MAPI_E_CALL_FAILED: A network problem was encountered during the transaction \sa OpenMessage */ _PUBLIC_ enum MAPISTATUS ReloadCachedInformation(mapi_object_t *obj_message) { struct mapi_context *mapi_ctx; struct mapi_request *mapi_request; struct mapi_response *mapi_response; struct EcDoRpc_MAPI_REQ *mapi_req; struct ReloadCachedInformation_req request; struct ReloadCachedInformation_repl *reply; struct mapi_session *session; mapi_object_message_t *message; struct SPropValue lpProp; NTSTATUS status; enum MAPISTATUS retval; uint32_t size = 0; TALLOC_CTX *mem_ctx; uint32_t i = 0; uint8_t logon_id; /* Sanity checks */ OPENCHANGE_RETVAL_IF(!obj_message, MAPI_E_INVALID_PARAMETER, NULL); session = mapi_object_get_session(obj_message); OPENCHANGE_RETVAL_IF(!session, MAPI_E_INVALID_PARAMETER, NULL); mapi_ctx = session->mapi_ctx; OPENCHANGE_RETVAL_IF(!mapi_ctx, MAPI_E_NOT_INITIALIZED, NULL); if ((retval = mapi_object_get_logon_id(obj_message, &logon_id)) != MAPI_E_SUCCESS) return retval; mem_ctx = talloc_named(session, 0, "ReloadCachedInformation"); /* Fill the ReloadCachedInformation operation */ request.Reserved = 0x0000; size += sizeof (uint16_t); /* Fill the MAPI_REQ request */ mapi_req = talloc_zero(mem_ctx, struct EcDoRpc_MAPI_REQ); mapi_req->opnum = op_MAPI_ReloadCachedInformation; mapi_req->logon_id = logon_id; mapi_req->handle_idx = 0; mapi_req->u.mapi_ReloadCachedInformation = request; size += 5; /* Fill the mapi_request structure */ mapi_request = talloc_zero(mem_ctx, struct mapi_request); mapi_request->mapi_len = size + sizeof (uint32_t); mapi_request->length = size; mapi_request->mapi_req = mapi_req; mapi_request->handles = talloc_array(mem_ctx, uint32_t, 1); mapi_request->handles[0] = mapi_object_get_handle(obj_message); status = emsmdb_transaction_wrapper(session, mem_ctx, mapi_request, &mapi_response); OPENCHANGE_RETVAL_IF(!NT_STATUS_IS_OK(status), MAPI_E_CALL_FAILED, mem_ctx); OPENCHANGE_RETVAL_IF(!mapi_response->mapi_repl, MAPI_E_CALL_FAILED, mem_ctx); retval = mapi_response->mapi_repl->error_code; OPENCHANGE_RETVAL_IF(retval, retval, mem_ctx); OPENCHANGE_CHECK_NOTIFICATION(session, mapi_response); /* Store ReloadCachedInformation reply data */ reply = &mapi_response->mapi_repl->u.mapi_ReloadCachedInformation; message = talloc_zero((TALLOC_CTX *)session, mapi_object_message_t); message->cValues = reply->RecipientColumns.cValues; message->SRowSet.cRows = reply->RowCount; message->SRowSet.aRow = talloc_array((TALLOC_CTX *)message, struct SRow, reply->RowCount + 1); message->SPropTagArray.cValues = reply->RecipientColumns.cValues; message->SPropTagArray.aulPropTag = talloc_steal(message, reply->RecipientColumns.aulPropTag); for (i = 0; i < reply->RowCount; i++) { emsmdb_get_SRow((TALLOC_CTX *)message, &(message->SRowSet.aRow[i]), &message->SPropTagArray, reply->RecipientRows[i].RecipientRow.prop_count, &reply->RecipientRows[i].RecipientRow.prop_values, reply->RecipientRows[i].RecipientRow.layout, 1); lpProp.ulPropTag = PR_RECIPIENT_TYPE; lpProp.value.l = reply->RecipientRows[i].RecipientType; SRow_addprop(&(message->SRowSet.aRow[i]), lpProp); lpProp.ulPropTag = PR_INTERNET_CPID; lpProp.value.l = reply->RecipientRows[i].CodePageId; SRow_addprop(&(message->SRowSet.aRow[i]), lpProp); } /* add SPropTagArray elements we automatically append to SRow */ SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_RECIPIENT_TYPE); SPropTagArray_add((TALLOC_CTX *)message, &message->SPropTagArray, PR_INTERNET_CPID); talloc_free(obj_message->private_data); obj_message->private_data = (void *) message; talloc_free(mapi_response); talloc_free(mem_ctx); errno = 0; return MAPI_E_SUCCESS; }
/** Convert module specific attribute id to value_pair_tmpl_t. * * @param[in] ctx for talloc * @param[in] name string to convert. * @param[in] type Type of quoting around value. * @return pointer to new VPT. */ value_pair_tmpl_t *radius_str2tmpl(TALLOC_CTX *ctx, char const *name, FR_TOKEN type) { value_pair_tmpl_t *vpt; vpt = talloc_zero(ctx, value_pair_tmpl_t); vpt->name = talloc_strdup(vpt, name); switch (type) { case T_BARE_WORD: if (*name == '&') name++; if (!isdigit((int) *name)) { request_refs_t ref; pair_lists_t list; char const *p = name; ref = radius_request_name(&p, REQUEST_CURRENT); if (ref == REQUEST_UNKNOWN) goto literal; list = radius_list_name(&p, PAIR_LIST_REQUEST); if (list == PAIR_LIST_UNKNOWN) goto literal; if ((p != name) && !*p) { vpt->type = VPT_TYPE_LIST; } else { DICT_ATTR const *da; da = dict_attrbyname(p); if (!da) { vpt->type = VPT_TYPE_LITERAL; break; } vpt->da = da; vpt->type = VPT_TYPE_ATTR; } vpt->request = ref; vpt->list = list; break; } /* FALL-THROUGH */ case T_SINGLE_QUOTED_STRING: literal: vpt->type = VPT_TYPE_LITERAL; break; case T_DOUBLE_QUOTED_STRING: vpt->type = VPT_TYPE_XLAT; break; case T_BACK_QUOTED_STRING: vpt->type = VPT_TYPE_EXEC; break; case T_OP_REG_EQ: /* hack */ vpt->type = VPT_TYPE_REGEX; break; default: rad_assert(0); return NULL; } return vpt; }
/* * Create an access check structure, the format depends on the version parameter. * If broken is specified then we create a stucture that isn't conform to the * specification. * * If the structure can't be created then NULL is returned. */ static DATA_BLOB *create_access_check(struct torture_context *tctx, struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, const char *user, bool broken, uint32_t version) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); DATA_BLOB *blob = talloc_zero(mem_ctx, DATA_BLOB); enum ndr_err_code ndr_err; const struct dom_sid *sid = get_user_sid(tctx, p, tmp_ctx, user); if (sid == NULL) { return NULL; } if (version == 2) { struct bkrp_access_check_v2 access_struct; struct sha sctx; uint8_t nonce[32]; ZERO_STRUCT(access_struct); generate_random_buffer(nonce, sizeof(nonce)); access_struct.nonce_len = sizeof(nonce); access_struct.nonce = nonce; access_struct.sid = *sid; ndr_err = ndr_push_struct_blob(blob, blob, &access_struct, (ndr_push_flags_fn_t)ndr_push_bkrp_access_check_v2); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return NULL; } /* * We pushed the whole structure including a null hash * but the hash need to be calculated only up to the hash field * so we reduce the size of what has to be calculated */ SHA1_Init(&sctx); SHA1_Update(&sctx, blob->data, blob->length - sizeof(access_struct.hash)); SHA1_Final(blob->data + blob->length - sizeof(access_struct.hash), &sctx); /* Altering the SHA */ if (broken) { blob->data[blob->length - 1]++; } } if (version == 3) { struct bkrp_access_check_v3 access_struct; struct hc_sha512state sctx; uint8_t nonce[32]; ZERO_STRUCT(access_struct); generate_random_buffer(nonce, sizeof(nonce)); access_struct.nonce_len = sizeof(nonce); access_struct.nonce = nonce; access_struct.sid = *sid; ndr_err = ndr_push_struct_blob(blob, blob, &access_struct, (ndr_push_flags_fn_t)ndr_push_bkrp_access_check_v3); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return NULL; } /*We pushed the whole structure including a null hash * but the hash need to be calculated only up to the hash field * so we reduce the size of what has to be calculated */ SHA512_Init(&sctx); SHA512_Update(&sctx, blob->data, blob->length - sizeof(access_struct.hash)); SHA512_Final(blob->data + blob->length - sizeof(access_struct.hash), &sctx); /* Altering the SHA */ if (broken) { blob->data[blob->length -1]++; } } talloc_free(tmp_ctx); return blob; }
/** Convert CONFIG_PAIR (which may contain refs) to value_pair_map_t. * * Treats the left operand as an attribute reference * @verbatim<request>.<list>.<attribute>@endverbatim * * Treatment of left operand depends on quotation, barewords are treated as * attribute references, double quoted values are treated as expandable strings, * single quoted values are treated as literal strings. * * Return must be freed with talloc_free * * @param[in] ctx for talloc * @param[in] cp to convert to map. * @param[in] dst_request_def The default request to insert unqualified * attributes into. * @param[in] dst_list_def The default list to insert unqualified attributes * into. * @param[in] src_request_def The default request to resolve attribute * references in. * @param[in] src_list_def The default list to resolve unqualified attributes * in. * @return value_pair_map_t if successful or NULL on error. */ value_pair_map_t *radius_cp2map(TALLOC_CTX *ctx, CONF_PAIR *cp, request_refs_t dst_request_def, pair_lists_t dst_list_def, request_refs_t src_request_def, pair_lists_t src_list_def) { value_pair_map_t *map; char const *attr; char const *value; FR_TOKEN type; CONF_ITEM *ci = cf_pairtoitem(cp); if (!cp) return NULL; map = talloc_zero(ctx, value_pair_map_t); attr = cf_pair_attr(cp); value = cf_pair_value(cp); if (!value) { cf_log_err(ci, "Missing attribute value"); goto error; } map->dst = radius_attr2tmpl(map, attr, dst_request_def, dst_list_def); if (!map->dst) { cf_log_err(ci, "Syntax error in attribute definition"); goto error; } /* * Bare words always mean attribute references. */ type = cf_pair_value_type(cp); if (type == T_BARE_WORD) { if (*value == '&') { map->src = radius_attr2tmpl(map, value + 1, src_request_def, src_list_def); } else { if (!isdigit((int) *value) && ((strchr(value, ':') != NULL) || (dict_attrbyname(value) != NULL))) { map->src = radius_attr2tmpl(map, value, src_request_def, src_list_def); } if (map->src) { WDEBUG("%s[%d]: Please add '&' for attribute reference '%s = &%s'", cf_pair_filename(cp), cf_pair_lineno(cp), attr, value); } else { map->src = radius_str2tmpl(map, value, type); } } } else { map->src = radius_str2tmpl(map, value, type); } if (!map->src) { goto error; } map->op = cf_pair_operator(cp); map->ci = ci; /* * Lots of sanity checks for insane people... */ /* * We don't support implicit type conversion, * except for "octets" */ if (map->dst->da && map->src->da && (map->src->da->type != map->dst->da->type) && (map->src->da->type != PW_TYPE_OCTETS) && (map->dst->da->type != PW_TYPE_OCTETS)) { cf_log_err(ci, "Attribute type mismatch"); goto error; } /* * What exactly where you expecting to happen here? */ if ((map->dst->type == VPT_TYPE_ATTR) && (map->src->type == VPT_TYPE_LIST)) { cf_log_err(ci, "Can't copy list into an attribute"); goto error; } /* * Can't copy an xlat expansion or literal into a list, * we don't know what type of attribute we'd need * to create */ if ((map->dst->type == VPT_TYPE_LIST) && ((map->src->type == VPT_TYPE_XLAT) || (map->src->type == VPT_TYPE_LITERAL))) { cf_log_err(ci, "Can't copy value into list (we don't know which attribute to create)"); goto error; } /* * Depending on the attribute type, some operators are * disallowed. */ if (map->dst->type == VPT_TYPE_ATTR) { if ((map->op != T_OP_EQ) && (map->op != T_OP_CMP_EQ) && (map->op != T_OP_ADD) && (map->op != T_OP_SUB) && (map->op != T_OP_LE) && (map->op != T_OP_GE) && (map->op != T_OP_CMP_FALSE) && (map->op != T_OP_SET)) { cf_log_err(ci, "Invalid operator for attribute"); goto error; } } switch (map->src->type) { /* * Only += and -= operators are supported for list copy. */ case VPT_TYPE_LIST: switch (map->op) { case T_OP_SUB: case T_OP_ADD: break; default: cf_log_err(ci, "Operator \"%s\" not allowed " "for list copy", fr_int2str(fr_tokens, map->op, "<INVALID>")); goto error; } break; default: break; } return map; error: talloc_free(map); return NULL; }
/** Locate a cache entry in redis * * @copydetails cache_entry_find_t */ static cache_status_t cache_entry_find(rlm_cache_entry_t **out, UNUSED rlm_cache_config_t const *config, void *driver_inst, REQUEST *request, UNUSED void *handle, uint8_t const *key, size_t key_len) { rlm_cache_redis_t *driver = driver_inst; size_t i; fr_redis_cluster_state_t state; fr_redis_conn_t *conn; fr_redis_rcode_t status; redisReply *reply = NULL; int s_ret; vp_map_t *head = NULL, **last = &head; #ifdef HAVE_TALLOC_POOLED_OBJECT size_t pool_size = 0; #endif rlm_cache_entry_t *c; for (s_ret = fr_redis_cluster_state_init(&state, &conn, driver->cluster, request, key, key_len, false); s_ret == REDIS_RCODE_TRY_AGAIN; /* Continue */ s_ret = fr_redis_cluster_state_next(&state, &conn, driver->cluster, request, status, &reply)) { /* * Grab all the data for this hash, should return an array * of alternating keys/values which we then convert into maps. */ if (RDEBUG_ENABLED3) { char *p; p = fr_asprint(NULL, (char const *)key, key_len, '"'); RDEBUG3("LRANGE %s 0 -1", key); talloc_free(p); } reply = redisCommand(conn->handle, "LRANGE %b 0 -1", key, key_len); status = fr_redis_command_status(conn, reply); } if (s_ret != REDIS_RCODE_SUCCESS) { RERROR("Failed retrieving entry"); fr_redis_reply_free(reply); return CACHE_ERROR; } rad_assert(reply); /* clang scan */ if (reply->type != REDIS_REPLY_ARRAY) { REDEBUG("Bad result type, expected array, got %s", fr_int2str(redis_reply_types, reply->type, "<UNKNOWN>")); fr_redis_reply_free(reply); return CACHE_ERROR; } RDEBUG3("Entry contains %zu elements", reply->elements); if (reply->elements == 0) { fr_redis_reply_free(reply); return CACHE_MISS; } if (reply->elements % 3) { REDEBUG("Invalid number of reply elements (%zu). " "Reply must contain triplets of keys operators and values", reply->elements); fr_redis_reply_free(reply); return CACHE_ERROR; } #ifdef HAVE_TALLOC_POOLED_OBJECT /* * We can get a pretty good idea of the required size of the pool */ for (i = 0; i < reply->elements; i += 3) { pool_size += sizeof(vp_map_t) + (sizeof(vp_tmpl_t) * 2); if (reply->element[i]->type == REDIS_REPLY_STRING) pool_size += reply->element[i]->len + 1; } /* * reply->elements gives us the number of chunks, as the maps are triplets, and there * are three chunks per map */ c = talloc_pooled_object(NULL, rlm_cache_entry_t, reply->elements, pool_size); memset(&pool, 0, sizeof(rlm_cache_entry_t)); #else c = talloc_zero(NULL, rlm_cache_entry_t); #endif /* * Convert the key/value pairs back into maps */ for (i = 0; i < reply->elements; i += 3) { if (fr_redis_reply_to_map(c, last, request, reply->element[i], reply->element[i + 1], reply->element[i + 2]) < 0) { talloc_free(c); fr_redis_reply_free(reply); return CACHE_ERROR; } last = &(*last)->next; } fr_redis_reply_free(reply); /* * Pull out the cache created date */ if ((head->lhs->tmpl_da->vendor == 0) && (head->lhs->tmpl_da->attr == PW_CACHE_CREATED)) { vp_map_t *map; c->created = head->rhs->tmpl_data_value.date; map = head; head = head->next; talloc_free(map); } /* * Pull out the cache expires date */ if ((head->lhs->tmpl_da->vendor == 0) && (head->lhs->tmpl_da->attr == PW_CACHE_EXPIRES)) { vp_map_t *map; c->expires = head->rhs->tmpl_data_value.date; map = head; head = head->next; talloc_free(map); } c->key = talloc_memdup(c, key, key_len); c->key_len = key_len; c->maps = head; *out = c; return CACHE_OK; }
/** Configure EAP-ikev2 handler * */ static int mod_instantiate(CONF_SECTION *conf, void **instance) { int ret; struct ikev2_ctx *i2; rlm_eap_ikev2_t *inst; char *server_auth_type, *default_auth_type, *users_file_name; ikev2_set_log_callback(vxlogf); inst = talloc_zero(conf, rlm_eap_ikev2_t); if (cf_section_parse(conf, &inst, module_config) < 0) return -1; i2 = Create_ikev2_ctx(); if (!i2) return -1; *instance = i2; /* * Map our config structure onto the IKEv2 context */ memcpy(&i2->trusted, &inst->tls_ca_file, sizeof(i2->trusted)); memcpy(&i2->pkfile, &inst->tls_private_key_file, sizeof(i2->pkfile)); memcpy(&i2->pkfile_pwd, &inst->tls_private_key_password, sizeof(i2->pkfile_pwd)); memcpy(&i2->certfile, &inst->tls_certificate_file, sizeof(i2->certfile)); memcpy(&i2->id, &inst->id, sizeof(i2->id)); i2->max_fragment_size = inst->max_fragment_size; i2->DHCounterMax = inst->dh_counter_max; i2->sendCertReq = (uint8_t) inst->send_cert_request; i2->fastExpire = inst->fast_expire; i2->enableFastDHEx = inst->enable_fast_dhex; i2->enableFastReconnect = inst->enable_fast_reconnect; memcpy(&server_auth_type, &inst->server_auth_type, sizeof(server_auth_type)); memcpy(&default_auth_type, &inst->default_auth_type, sizeof(default_auth_type)); memcpy(&users_file_name, &inst->users_file_name, sizeof(users_file_name)); hexalize(&i2->id, &i2->idlen); i2->authtype = rad_get_authtype(server_auth_type); if (!i2->id) { ERROR(IKEv2_LOG_PREFIX "'id' configuration option is required!!!"); return -1; } switch (i2->authtype) { default: case IKEv2_AUTH_SK: break; case IKEv2_AUTH_CERT: if (!i2->certfile || !i2->pkfile) { ERROR(IKEv2_LOG_PREFIX "'certificate_file' and 'private_key_file' items are required " "for 'cert' auth type"); return -1; } if (!file_exists(i2->certfile)) { ERROR(IKEv2_LOG_PREFIX "Can not open 'certificate_file' %s", i2->certfile); return -1; } if (!file_exists(i2->pkfile)) { ERROR(IKEv2_LOG_PREFIX "Can not open 'private_key_file' %s",i2->pkfile); return -1; } break; } if (!i2->trusted) { AUTH(IKEv2_LOG_PREFIX "'ca_file' item not set, client cert based authentication will fail"); } else { if (!file_exists(i2->trusted)) { ERROR(IKEv2_LOG_PREFIX "Can not open 'ca_file' %s", i2->trusted); return -1; } } if (i2->crl_file) { if (!file_exists(i2->crl_file)) { ERROR(IKEv2_LOG_PREFIX "Can not open 'crl_file' %s", i2->crl_file); return -1; } } i2->idtype = IdTypeFromName(inst->server_id_type); if (i2->idtype <= 0) { ERROR(IKEv2_LOG_PREFIX "Unsupported 'idtype': %s", inst->server_id_type); return -1; } if (rad_load_proposals(i2, conf)) { ERROR(IKEv2_LOG_PREFIX "Failed to load proposals"); return -1; } ret = rad_load_credentials(instance, i2, users_file_name, default_auth_type); if (ret == -1) { ERROR(IKEv2_LOG_PREFIX "Error while loading users credentials"); return -1; } i2->x509_store = NULL; if(CertInit(i2)){ ERROR(IKEv2_LOG_PREFIX "Error while loading certs/crl"); return -1; } return 0; }
/* Lookup group membership given a rid. */ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, const DOM_SID *group_sid, uint32 *num_names, DOM_SID ***sid_mem, char ***names, uint32 **name_types) { CLI_POLICY_HND *hnd = NULL; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 i, total_names = 0; POLICY_HND dom_pol, group_pol; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; BOOL got_dom_pol = False, got_group_pol = False; uint32 *rid_mem = NULL; uint32 group_rid; int retry; unsigned int j; fstring sid_string; DEBUG(10,("rpc: lookup_groupmem %s sid=%s\n", domain->name, sid_to_string(sid_string, group_sid))); if (!sid_peek_check_rid(&domain->sid, group_sid, &group_rid)) { goto done; } *num_names = 0; retry = 0; do { /* Get sam handle */ if (!NT_STATUS_IS_OK(result = cm_get_sam_handle(domain, &hnd))) goto done; /* Get domain handle */ result = cli_samr_open_domain(hnd->cli, mem_ctx, &hnd->pol, des_access, &domain->sid, &dom_pol); } while (!NT_STATUS_IS_OK(result) && (retry++ < 1) && hnd && hnd->cli && hnd->cli->fd == -1); if (!NT_STATUS_IS_OK(result)) goto done; got_dom_pol = True; /* Get group handle */ result = cli_samr_open_group(hnd->cli, mem_ctx, &dom_pol, des_access, group_rid, &group_pol); if (!NT_STATUS_IS_OK(result)) goto done; got_group_pol = True; /* Step #1: Get a list of user rids that are the members of the group. */ result = cli_samr_query_groupmem(hnd->cli, mem_ctx, &group_pol, num_names, &rid_mem, name_types); if (!NT_STATUS_IS_OK(result)) goto done; if (!*num_names) { names = NULL; name_types = NULL; sid_mem = NULL; goto done; } /* Step #2: Convert list of rids into list of usernames. Do this in bunches of ~1000 to avoid crashing NT4. It looks like there is a buffer overflow or something like that lurking around somewhere. */ #define MAX_LOOKUP_RIDS 900 *names = talloc_zero(mem_ctx, *num_names * sizeof(char *)); *name_types = talloc_zero(mem_ctx, *num_names * sizeof(uint32)); *sid_mem = talloc_zero(mem_ctx, *num_names * sizeof(DOM_SID *)); for (j=0;j<(*num_names);j++) { (*sid_mem)[j] = rid_to_talloced_sid(domain, mem_ctx, (rid_mem)[j]); } if (*num_names>0 && (!*names || !*name_types)) { result = NT_STATUS_NO_MEMORY; goto done; } for (i = 0; i < *num_names; i += MAX_LOOKUP_RIDS) { int num_lookup_rids = MIN(*num_names - i, MAX_LOOKUP_RIDS); uint32 tmp_num_names = 0; char **tmp_names = NULL; uint32 *tmp_types = NULL; /* Lookup a chunk of rids */ result = cli_samr_lookup_rids(hnd->cli, mem_ctx, &dom_pol, 1000, /* flags */ num_lookup_rids, &rid_mem[i], &tmp_num_names, &tmp_names, &tmp_types); /* see if we have a real error (and yes the STATUS_SOME_UNMAPPED is the one returned from 2k) */ if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED)) goto done; /* Copy result into array. The talloc system will take care of freeing the temporary arrays later on. */ memcpy(&(*names)[i], tmp_names, sizeof(char *) * tmp_num_names); memcpy(&(*name_types)[i], tmp_types, sizeof(uint32) * tmp_num_names); total_names += tmp_num_names; } *num_names = total_names; result = NT_STATUS_OK; done: if (got_group_pol) cli_samr_close(hnd->cli, mem_ctx, &group_pol); if (got_dom_pol) cli_samr_close(hnd->cli, mem_ctx, &dom_pol); return result; }
static bool api_atsvc_JobAdd(struct pipes_struct *p) { const struct ndr_interface_call *call; struct ndr_pull *pull; struct ndr_push *push; enum ndr_err_code ndr_err; struct atsvc_JobAdd *r; call = &ndr_table_atsvc.calls[NDR_ATSVC_JOBADD]; r = talloc(talloc_tos(), struct atsvc_JobAdd); if (r == NULL) { return false; } pull = ndr_pull_init_blob(&p->in_data.data, r); if (pull == NULL) { talloc_free(r); return false; } pull->flags |= LIBNDR_FLAG_REF_ALLOC; if (p->endian) { pull->flags |= LIBNDR_FLAG_BIGENDIAN; } ndr_err = call->ndr_pull(pull, NDR_IN, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(atsvc_JobAdd, NDR_IN, r); } ZERO_STRUCT(r->out); r->out.job_id = talloc_zero(r, uint32_t); if (r->out.job_id == NULL) { talloc_free(r); return false; } r->out.result = _atsvc_JobAdd(p, r); if (p->fault_state) { talloc_free(r); /* Return true here, srv_pipe_hnd.c will take care */ return true; } if (DEBUGLEVEL >= 10) { NDR_PRINT_FUNCTION_DEBUG(atsvc_JobAdd, NDR_OUT | NDR_SET_VALUES, r); } push = ndr_push_init_ctx(r); if (push == NULL) { talloc_free(r); return false; } /* * carry over the pointer count to the reply in case we are * using full pointer. See NDR specification for full pointers */ push->ptr_count = pull->ptr_count; ndr_err = call->ndr_push(push, NDR_OUT, r); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(r); return false; } p->out_data.rdata = ndr_push_blob(push); talloc_steal(p->mem_ctx, p->out_data.rdata.data); talloc_free(r); return true; }
static ssize_t xlat_tokenize_literal(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head, int brace, char const **error) { char *p, *q; xlat_exp_t *node; if (!*fmt) return 0; XLAT_DEBUG("LITERAL: %s", fmt); node = talloc_zero(ctx, xlat_exp_t); node->fmt = fmt; node->len = 0; node->type = XLAT_LITERAL; p = fmt; q = fmt; while (*p) { /* * Convert \n to it's literal representation. */ if (p[0] == '\\') switch (p[1]) { case 't': *(q++) = '\t'; p += 2; node->len++; continue; case 'n': *(q++) = '\n'; p += 2; node->len++; continue; case 'x': p += 2; if (!p[0] || !p[1]) { talloc_free(node); *error = "Hex expansion requires two hex digits"; return -(p - fmt); } if (!fr_hex2bin((uint8_t *) q, p, 2)) { talloc_free(node); *error = "Invalid hex characters"; return -(p - fmt); } /* * Don't let people shoot themselves in the foot. * \x00 is forbidden. */ if (!*q) { talloc_free(node); *error = "Cannot add zero byte to printable string"; return -(p - fmt); } p += 2; q++; node->len++; continue; default: *(q++) = *p; p += 2; node->len++; continue; } /* * Process the expansion. */ if ((p[0] == '%') && (p[1] == '{')) { ssize_t slen; XLAT_DEBUG("LITERAL: %s --> %s", node->fmt, p); slen = xlat_tokenize_expansion(node, p, &node->next, error); if (slen <= 0) { talloc_free(node); return slen - (p - fmt); } *p = '\0'; /* end the literal */ p += slen; rad_assert(node->next != NULL); /* * Short-circuit the recursive call. * This saves another function call and * memory allocation. */ if (!*p) break; /* * "foo %{User-Name} bar" * LITERAL "foo " * EXPANSION User-Name * LITERAL " bar" */ slen = xlat_tokenize_literal(node->next, p, &(node->next->next), brace, error); rad_assert(slen != 0); if (slen < 0) { talloc_free(node); return slen - (p - fmt); } p += slen; break; /* stop processing the string */ } /* * Check for valid single-character expansions. */ if (p[0] == '%') { ssize_t slen; xlat_exp_t *next; if (!p[1] || !strchr("%dlmtDGHISTY", p[1])) { talloc_free(node); *error = "Invalid variable expansion"; p++; return - (p - fmt); } XLAT_DEBUG("PERCENT: %s --> %c", node->fmt, p[1]); next = talloc_zero(node, xlat_exp_t); next->fmt = p + 1; next->len = 1; next->type = XLAT_PERCENT; node->next = next; *p = '\0'; p += 2; if (!*p) break; /* * And recurse. */ slen = xlat_tokenize_literal(node->next, p, &(node->next->next), brace, error); rad_assert(slen != 0); if (slen < 0) { talloc_free(node); return slen - (p - fmt); } p += slen; break; /* stop processing the string */ } /* * If required, eat the brace. */ if (brace && (*p == '}')) { *q = '\0'; p++; break; } *(q++) = *(p++); node->len++; } /* * Squash zero-width literals */ if (node->len > 0) { *head = node; } else { (void) talloc_steal(ctx, node->next); *head = node->next; talloc_free(node); } return p - fmt; }
/* * Find a module on disk or in memory, and link to it. */ static module_entry_t *linkto_module(char const *module_name, CONF_SECTION *cs) { module_entry_t myentry; module_entry_t *node; void *handle = NULL; const module_t *module; strlcpy(myentry.name, module_name, sizeof(myentry.name)); node = rbtree_finddata(module_tree, &myentry); if (node) return node; /* * Link to the module's rlm_FOO{} structure, the same as * the module name. */ #if !defined(WITH_LIBLTDL) && defined(HAVE_DLFCN_H) && defined(RTLD_SELF) module = dlsym(RTLD_SELF, module_name); if (module) goto open_self; #endif /* * Keep the handle around so we can dlclose() it. */ handle = lt_dlopenext(module_name); if (!handle) { cf_log_err_cs(cs, "Failed to link to module '%s': %s\n", module_name, dlerror()); return NULL; } DEBUG3(" (Loaded %s, checking if it's valid)", module_name); /* * libltld MAY core here, if the handle it gives us contains * garbage data. */ module = dlsym(handle, module_name); if (!module) { cf_log_err_cs(cs, "Failed linking to %s structure: %s\n", module_name, dlerror()); dlclose(handle); return NULL; } #if !defined(WITH_LIBLTDL) && defined (HAVE_DLFCN_H) && defined(RTLD_SELF) open_self: #endif /* * Before doing anything else, check if it's sane. */ if (module->magic != RLM_MODULE_MAGIC_NUMBER) { dlclose(handle); cf_log_err_cs(cs, "Invalid version in module '%s'", module_name); return NULL; } /* make room for the module type */ node = talloc_zero(cs, module_entry_t); talloc_set_destructor((void *) node, module_entry_free); strlcpy(node->name, module_name, sizeof(node->name)); node->module = module; node->handle = handle; cf_log_module(cs, "Loaded module %s", module_name); /* * Add the module as "rlm_foo-version" to the configuration * section. */ if (!rbtree_insert(module_tree, node)) { ERROR("Failed to cache module %s", module_name); dlclose(handle); talloc_free(node); return NULL; } return node; }
static ssize_t xlat_tokenize_alternation(TALLOC_CTX *ctx, char *fmt, xlat_exp_t **head, char const **error) { ssize_t slen; char *p; xlat_exp_t *node; rad_assert(fmt[0] == '%'); rad_assert(fmt[1] == '{'); rad_assert(fmt[2] == '%'); rad_assert(fmt[3] == '{'); XLAT_DEBUG("ALTERNATE: %s", fmt); node = talloc_zero(ctx, xlat_exp_t); node->type = XLAT_ALTERNATE; p = fmt + 2; slen = xlat_tokenize_expansion(node, p, &node->child, error); if (slen <= 0) { talloc_free(node); return slen - (p - fmt); } p += slen; if (p[0] != ':') { talloc_free(node); *error = "Expected ':' after first expansion"; return -(p - fmt); } p++; if (p[0] != '-') { talloc_free(node); *error = "Expected '-' after ':'"; return -(p - fmt); } p++; /* * Allow the RHS to be empty as a special case. */ if (*p == '}') { /* * Hack up an empty string. */ node->alternate = talloc_zero(node, xlat_exp_t); node->alternate->type = XLAT_LITERAL; node->alternate->fmt = talloc_strdup(node->alternate, ""); *(p++) = '\0'; } else { slen = xlat_tokenize_literal(node, p, &node->alternate, true, error); if (slen <= 0) { talloc_free(node); return slen - (p - fmt); } if (!node->alternate) { talloc_free(node); *error = "Empty expansion is invalid"; return -(p - fmt); } p += slen; } *head = node; return p - fmt; }
static int dxva2_init(struct lavc_ctx *s) { DXVA2Context *ctx; pCreateDeviceManager9 *createDeviceManager = NULL; HRESULT hr; unsigned resetToken = 0; ctx = talloc_zero(NULL, DXVA2Context); if (!ctx) return -1; s->hwdec_priv = ctx; ctx->log = mp_log_new(s, s->log, "dxva2"); ctx->sw_pool = talloc_steal(ctx, mp_image_pool_new(17)); mp_check_gpu_memcpy(ctx->log, NULL); ctx->deviceHandle = INVALID_HANDLE_VALUE; ctx->dxva2lib = LoadLibrary(L"dxva2.dll"); if (!ctx->dxva2lib) { MP_ERR(ctx, "Failed to load DXVA2 library\n"); goto fail; } if (create_device(s) < 0) goto fail; createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(ctx->dxva2lib, "DXVA2CreateDirect3DDeviceManager9"); if (!createDeviceManager) { MP_ERR(ctx, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n"); goto fail; } hr = createDeviceManager(&resetToken, &ctx->d3d9devmgr); if (FAILED(hr)) { MP_ERR(ctx, "Failed to create Direct3D device manager\n"); goto fail; } hr = IDirect3DDeviceManager9_ResetDevice(ctx->d3d9devmgr, ctx->d3d9device, resetToken); if (FAILED(hr)) { MP_ERR(ctx, "Failed to bind Direct3D device to device manager\n"); goto fail; } hr = IDirect3DDeviceManager9_OpenDeviceHandle(ctx->d3d9devmgr, &ctx->deviceHandle); if (FAILED(hr)) { MP_ERR(ctx, "Failed to open device handle\n"); goto fail; } hr = IDirect3DDeviceManager9_GetVideoService(ctx->d3d9devmgr, ctx->deviceHandle, &IID_IDirectXVideoDecoderService, (void **)&ctx->decoder_service); if (FAILED(hr)) { MP_ERR(ctx, "Failed to create IDirectXVideoDecoderService\n"); goto fail; } s->avctx->hwaccel_context = av_mallocz(sizeof(struct dxva_context)); if (!s->avctx->hwaccel_context) goto fail; return 0; fail: dxva2_uninit(s); return -1; }