Ejemplo n.º 1
0
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;

    tv_param_t *params = m_sub_options_copy(demuxer, &tv_params_conf,
                                            demuxer->opts->tv_params);
    struct tv_stream_params *sparams = demuxer->stream->priv;
    if (sparams->channel && sparams->channel[0]) {
        talloc_free(params->channel);
        params->channel = talloc_strdup(NULL, sparams->channel);
    }
    if (sparams->input >= 0)
        params->input = sparams->input;

    assert(demuxer->priv==NULL);
    if(!(tvh=tv_begin(params, 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->audio = 0;
        }

    /* 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->audio && 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_fmt2bps(audio_format);
        int block_align = samplesize * sh_audio->channels.num;
        int bytes_per_second = sh_audio->samplerate * block_align;

        sh_audio->bitrate = bytes_per_second * 8;

        // 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 = block_align;
        sh_audio->wf->nAvgBytesPerSec = bytes_per_second;

        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;
}
Ejemplo n.º 2
0
static NTSTATUS map_populate_groups(TALLOC_CTX *mem_ctx,
				    GROUPMAP *groupmap,
				    ACCOUNTMAP *accountmap,
				    const char *sid,
				    const char *suffix,
				    const char *builtin_sid)
{
	char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ',');

	/* Map the groups created by populate_ldap_for_ldif */
	groupmap[0].rid		= 512;
	groupmap[0].gidNumber	= 512;
	groupmap[0].sambaSID	= talloc_asprintf(mem_ctx, "%s-512", sid);
	groupmap[0].group_dn	= talloc_asprintf(mem_ctx,
		"cn=Domain Admins,ou=%s,%s", group_attr, suffix);
	if (groupmap[0].sambaSID == NULL || groupmap[0].group_dn == NULL) {
		goto err;
	}

	accountmap[0].rid	= 512;
	accountmap[0].cn	= talloc_strdup(mem_ctx, "Domain Admins");
	if (accountmap[0].cn == NULL) {
		goto err;
	}

	groupmap[1].rid		= 513;
	groupmap[1].gidNumber	= 513;
	groupmap[1].sambaSID	= talloc_asprintf(mem_ctx, "%s-513", sid);
	groupmap[1].group_dn	= talloc_asprintf(mem_ctx,
		"cn=Domain Users,ou=%s,%s", group_attr, suffix);
	if (groupmap[1].sambaSID == NULL || groupmap[1].group_dn == NULL) {
		goto err;
	}

	accountmap[1].rid	= 513;
	accountmap[1].cn	= talloc_strdup(mem_ctx, "Domain Users");
	if (accountmap[1].cn == NULL) {
		goto err;
	}

	groupmap[2].rid		= 514;
	groupmap[2].gidNumber	= 514;
	groupmap[2].sambaSID	= talloc_asprintf(mem_ctx, "%s-514", sid);
	groupmap[2].group_dn	= talloc_asprintf(mem_ctx,
		"cn=Domain Guests,ou=%s,%s", group_attr, suffix);
	if (groupmap[2].sambaSID == NULL || groupmap[2].group_dn == NULL) {
		goto err;
	}

	accountmap[2].rid	= 514;
	accountmap[2].cn	= talloc_strdup(mem_ctx, "Domain Guests");
	if (accountmap[2].cn == NULL) {
		goto err;
	}

	groupmap[3].rid		= 515;
	groupmap[3].gidNumber	= 515;
	groupmap[3].sambaSID	= talloc_asprintf(mem_ctx, "%s-515", sid);
	groupmap[3].group_dn	= talloc_asprintf(mem_ctx,
		"cn=Domain Computers,ou=%s,%s", group_attr, suffix);
	if (groupmap[3].sambaSID == NULL || groupmap[3].group_dn == NULL) {
		goto err;
	}

	accountmap[3].rid	= 515;
	accountmap[3].cn	= talloc_strdup(mem_ctx, "Domain Computers");
	if (accountmap[3].cn == NULL) {
		goto err;
	}

	groupmap[4].rid		= 544;
	groupmap[4].gidNumber	= 544;
	groupmap[4].sambaSID	= talloc_asprintf(mem_ctx, "%s-544", builtin_sid);
	groupmap[4].group_dn	= talloc_asprintf(mem_ctx,
		"cn=Administrators,ou=%s,%s", group_attr, suffix);
	if (groupmap[4].sambaSID == NULL || groupmap[4].group_dn == NULL) {
		goto err;
	}

	accountmap[4].rid	= 515;
	accountmap[4].cn	= talloc_strdup(mem_ctx, "Administrators");
	if (accountmap[4].cn == NULL) {
		goto err;
	}

	groupmap[5].rid		= 550;
	groupmap[5].gidNumber	= 550;
	groupmap[5].sambaSID	= talloc_asprintf(mem_ctx, "%s-550", builtin_sid);
	groupmap[5].group_dn	= talloc_asprintf(mem_ctx,
		"cn=Print Operators,ou=%s,%s", group_attr, suffix);
	if (groupmap[5].sambaSID == NULL || groupmap[5].group_dn == NULL) {
		goto err;
	}

	accountmap[5].rid	= 550;
	accountmap[5].cn	= talloc_strdup(mem_ctx, "Print Operators");
	if (accountmap[5].cn == NULL) {
		goto err;
	}

	groupmap[6].rid		= 551;
	groupmap[6].gidNumber	= 551;
	groupmap[6].sambaSID	= talloc_asprintf(mem_ctx, "%s-551", builtin_sid);
	groupmap[6].group_dn	= talloc_asprintf(mem_ctx,
		"cn=Backup Operators,ou=%s,%s", group_attr, suffix);
	if (groupmap[6].sambaSID == NULL || groupmap[6].group_dn == NULL) {
		goto err;
	}

	accountmap[6].rid	= 551;
	accountmap[6].cn	= talloc_strdup(mem_ctx, "Backup Operators");
	if (accountmap[6].cn == NULL) {
		goto err;
	}

	groupmap[7].rid		= 552;
	groupmap[7].gidNumber	= 552;
	groupmap[7].sambaSID	= talloc_asprintf(mem_ctx, "%s-552", builtin_sid);
	groupmap[7].group_dn	= talloc_asprintf(mem_ctx,
		"cn=Replicators,ou=%s,%s", group_attr, suffix);
	if (groupmap[7].sambaSID == NULL || groupmap[7].group_dn == NULL) {
		goto err;
	}

	accountmap[7].rid	= 551;
	accountmap[7].cn	= talloc_strdup(mem_ctx, "Replicators");
	if (accountmap[7].cn == NULL) {
		goto err;
	}

	SAFE_FREE(group_attr);

	return NT_STATUS_OK;

  err:

	SAFE_FREE(group_attr);
	return NT_STATUS_NO_MEMORY;
}
Ejemplo n.º 3
0
static NTSTATUS ldif_init_context(TALLOC_CTX *mem_ctx,
				  enum netr_SamDatabaseID database_id,
				  const char *ldif_filename,
				  const char *domain_sid_str,
				  struct samsync_ldif_context **ctx)
{
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	struct samsync_ldif_context *r;
	const char *add_template = "/tmp/add.ldif.XXXXXX";
	const char *mod_template = "/tmp/mod.ldif.XXXXXX";
	const char *builtin_sid = "S-1-5-32";

	/* Get other smb.conf data */
	if (!(lp_workgroup()) || !*(lp_workgroup())) {
		DEBUG(0,("workgroup missing from smb.conf--exiting\n"));
		exit(1);
	}

	/* Get the ldap suffix */
	if (!(lp_ldap_suffix()) || !*(lp_ldap_suffix())) {
		DEBUG(0,("ldap suffix missing from smb.conf--exiting\n"));
		exit(1);
	}

	if (*ctx && (*ctx)->initialized) {
		return NT_STATUS_OK;
	}

	r = TALLOC_ZERO_P(mem_ctx, struct samsync_ldif_context);
	NT_STATUS_HAVE_NO_MEMORY(r);

	/* Get the ldap suffix */
	r->suffix = lp_ldap_suffix();

	/* Ensure we have an output file */
	if (ldif_filename) {
		r->ldif_file = fopen(ldif_filename, "a");
	} else {
		r->ldif_file = stdout;
	}

	if (!r->ldif_file) {
		fprintf(stderr, "Could not open %s\n", ldif_filename);
		DEBUG(1, ("Could not open %s\n", ldif_filename));
		status = NT_STATUS_UNSUCCESSFUL;
		goto done;
	}

	r->add_template = talloc_strdup(mem_ctx, add_template);
	r->mod_template = talloc_strdup(mem_ctx, mod_template);
	if (!r->add_template || !r->mod_template) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	r->add_name = talloc_strdup(mem_ctx, add_template);
	r->mod_name = talloc_strdup(mem_ctx, mod_template);
	if (!r->add_name || !r->mod_name) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	/* Open the add and mod ldif files */
	if (!(r->add_file = fdopen(smb_mkstemp(r->add_name),"w"))) {
		DEBUG(1, ("Could not open %s\n", r->add_name));
		status = NT_STATUS_UNSUCCESSFUL;
		goto done;
	}
	if (!(r->mod_file = fdopen(smb_mkstemp(r->mod_name),"w"))) {
		DEBUG(1, ("Could not open %s\n", r->mod_name));
		status = NT_STATUS_UNSUCCESSFUL;
		goto done;
	}

	/* Allocate initial memory for groupmap and accountmap arrays */
	r->groupmap = TALLOC_ZERO_ARRAY(mem_ctx, GROUPMAP, 8);
	r->accountmap = TALLOC_ZERO_ARRAY(mem_ctx, ACCOUNTMAP, 8);
	if (r->groupmap == NULL || r->accountmap == NULL) {
		DEBUG(1,("GROUPMAP talloc failed\n"));
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	/* Remember how many we malloced */
	r->num_alloced = 8;

	/* Initial database population */
	if (database_id == SAM_DATABASE_DOMAIN) {

		status = populate_ldap_for_ldif(domain_sid_str,
						r->suffix,
						builtin_sid,
						r->add_file);
		if (!NT_STATUS_IS_OK(status)) {
			goto done;
		}

		status = map_populate_groups(mem_ctx,
					     r->groupmap,
					     r->accountmap,
					     domain_sid_str,
					     r->suffix,
					     builtin_sid);
		if (!NT_STATUS_IS_OK(status)) {
			goto done;
		}
	}

	r->initialized = true;

	*ctx = r;

	return NT_STATUS_OK;
 done:
	TALLOC_FREE(r);
	return status;
}
Ejemplo n.º 4
0
static bool recreate_graph(struct af_instance *af, struct mp_audio *config)
{
    void *tmp = talloc_new(NULL);
    struct priv *p = af->priv;
    AVFilterContext *in = NULL, *out = NULL, *f_format = NULL;

    if (bstr0(p->cfg_graph).len == 0) {
        MP_FATAL(af, "lavfi: no filter graph set\n");
        return false;
    }

    destroy_graph(af);
    MP_VERBOSE(af, "lavfi: create graph: '%s'\n", p->cfg_graph);

    AVFilterGraph *graph = avfilter_graph_alloc();
    if (!graph)
        goto error;

    if (mp_set_avopts(af->log, graph, p->cfg_avopts) < 0)
        goto error;

    AVFilterInOut *outputs = avfilter_inout_alloc();
    AVFilterInOut *inputs  = avfilter_inout_alloc();
    if (!outputs || !inputs)
        goto error;

    // Build list of acceptable output sample formats. libavfilter will insert
    // conversion filters if needed.
    static const enum AVSampleFormat sample_fmts[] = {
        AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32,
        AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL,
        AV_SAMPLE_FMT_U8P, AV_SAMPLE_FMT_S16P, AV_SAMPLE_FMT_S32P,
        AV_SAMPLE_FMT_FLTP, AV_SAMPLE_FMT_DBLP,
        AV_SAMPLE_FMT_NONE
    };
    char *fmtstr = talloc_strdup(tmp, "");
    for (int n = 0; sample_fmts[n] != AV_SAMPLE_FMT_NONE; n++) {
        const char *name = av_get_sample_fmt_name(sample_fmts[n]);
        if (name) {
            const char *s = fmtstr[0] ? "|" : "";
            fmtstr = talloc_asprintf_append_buffer(fmtstr, "%s%s", s, name);
        }
    }

    char *src_args = talloc_asprintf(tmp,
        "sample_rate=%d:sample_fmt=%s:time_base=%d/%d:"
        "channel_layout=0x%"PRIx64,  config->rate,
        av_get_sample_fmt_name(af_to_avformat(config->format)),
        1, config->rate, mp_chmap_to_lavc(&config->channels));

    if (avfilter_graph_create_filter(&in, avfilter_get_by_name("abuffer"),
                                     "src", src_args, NULL, graph) < 0)
        goto error;

    if (avfilter_graph_create_filter(&out, avfilter_get_by_name("abuffersink"),
                                     "out", NULL, NULL, graph) < 0)
        goto error;

    if (avfilter_graph_create_filter(&f_format, avfilter_get_by_name("aformat"),
                                     "format", fmtstr, NULL, graph) < 0)
        goto error;

    if (avfilter_link(f_format, 0, out, 0) < 0)
        goto error;

    outputs->name = av_strdup("in");
    outputs->filter_ctx = in;

    inputs->name = av_strdup("out");
    inputs->filter_ctx = f_format;

    if (graph_parse(graph, p->cfg_graph, inputs, outputs, NULL) < 0)
        goto error;

    if (avfilter_graph_config(graph, NULL) < 0)
        goto error;

    p->in = in;
    p->out = out;
    p->graph = graph;

    assert(out->nb_inputs == 1);
    assert(in->nb_outputs == 1);

    talloc_free(tmp);
    return true;

error:
    MP_FATAL(af, "Can't configure libavfilter graph.\n");
    avfilter_graph_free(&graph);
    talloc_free(tmp);
    return false;
}
Ejemplo n.º 5
0
static WERROR reg_load_tree(REGF_FILE *regfile, const char *topkeypath,
			    REGF_NK_REC *key)
{
	REGF_NK_REC *subkey;
	struct registry_key_handle registry_key;
	struct regval_ctr *values;
	struct regsubkey_ctr *subkeys;
	int i;
	char *path = NULL;
	WERROR result = WERR_OK;

	/* initialize the struct registry_key_handle structure */

	registry_key.ops = reghook_cache_find(topkeypath);
	if (!registry_key.ops) {
		DEBUG(0, ("reg_load_tree: Failed to assign registry_ops "
			  "to [%s]\n", topkeypath));
		return WERR_BADFILE;
	}

	registry_key.name = talloc_strdup(regfile->mem_ctx, topkeypath);
	if (!registry_key.name) {
		DEBUG(0, ("reg_load_tree: Talloc failed for reg_key.name!\n"));
		return WERR_NOMEM;
	}

	/* now start parsing the values and subkeys */

	result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
	W_ERROR_NOT_OK_RETURN(result);

	result = regval_ctr_init(subkeys, &values);
	W_ERROR_NOT_OK_RETURN(result);

	/* copy values into the struct regval_ctr */

	for (i=0; i<key->num_values; i++) {
		regval_ctr_addvalue(values, key->values[i].valuename,
				    key->values[i].type,
				    key->values[i].data,
				    (key->values[i].data_size & ~VK_DATA_IN_OFFSET));
	}

	/* copy subkeys into the struct regsubkey_ctr */

	key->subkey_index = 0;
	while ((subkey = regfio_fetch_subkey( regfile, key ))) {
		result = regsubkey_ctr_addkey(subkeys, subkey->keyname);
		if (!W_ERROR_IS_OK(result)) {
			TALLOC_FREE(subkeys);
			return result;
		}
	}

	/* write this key and values out */

	if (!store_reg_values(&registry_key, values)
	    || !store_reg_keys(&registry_key, subkeys))
	{
		DEBUG(0,("reg_load_tree: Failed to load %s!\n", topkeypath));
		result = WERR_REG_IO_FAILURE;
	}

	TALLOC_FREE(subkeys);

	if (!W_ERROR_IS_OK(result)) {
		return result;
	}

	/* now continue to load each subkey registry tree */

	key->subkey_index = 0;
	while ((subkey = regfio_fetch_subkey(regfile, key))) {
		path = talloc_asprintf(regfile->mem_ctx,
				       "%s\\%s",
				       topkeypath,
				       subkey->keyname);
		if (path == NULL) {
			return WERR_NOMEM;
		}
		result = reg_load_tree(regfile, path, subkey);
		if (!W_ERROR_IS_OK(result)) {
			break;
		}
	}

	return result;
}
Ejemplo n.º 6
0
NTSTATUS passwd_to_SamInfo3(TALLOC_CTX *mem_ctx,
			    const char *unix_username,
			    const struct passwd *pwd,
			    struct netr_SamInfo3 **pinfo3,
			    struct extra_auth_info *extra)
{
	struct netr_SamInfo3 *info3;
	NTSTATUS status;
	TALLOC_CTX *tmp_ctx;
	const char *domain_name = NULL;
	const char *user_name = NULL;
	struct dom_sid domain_sid;
	struct dom_sid user_sid;
	struct dom_sid group_sid;
	enum lsa_SidType type;
	uint32_t num_sids = 0;
	struct dom_sid *user_sids = NULL;
	bool is_null;
	bool ok;

	tmp_ctx = talloc_stackframe();

	ok = lookup_name_smbconf(tmp_ctx,
				 unix_username,
				 LOOKUP_NAME_ALL,
				 &domain_name,
				 &user_name,
				 &user_sid,
				 &type);
	if (!ok) {
		status = NT_STATUS_NO_SUCH_USER;
		goto done;
	}

	if (type != SID_NAME_USER) {
		status = NT_STATUS_NO_SUCH_USER;
		goto done;
	}

	ok = winbind_lookup_usersids(tmp_ctx,
				     &user_sid,
				     &num_sids,
				     &user_sids);
	/* Check if winbind is running */
	if (ok) {
		/*
		 * Winbind is running and the first element of the user_sids
		 * is the primary group.
		 */
		if (num_sids > 0) {
			group_sid = user_sids[0];
		}
	} else {
		/*
		 * Winbind is not running, try to create the group_sid from the
		 * passwd group id.
		 */

		/*
		 * This can lead to a primary group of S-1-22-2-XX which
		 * will be rejected by other Samba code.
		 */
		gid_to_sid(&group_sid, pwd->pw_gid);
	}

	/*
	 * If we are a unix group, or a wellknown/builtin alias,
	 * set the group_sid to the
	 * 'Domain Users' RID of 513 which will always resolve to a
	 * name.
	 */
	if (sid_check_is_in_unix_groups(&group_sid) ||
	    sid_check_is_in_builtin(&group_sid) ||
	    sid_check_is_in_wellknown_domain(&group_sid)) {
		if (sid_check_is_in_unix_users(&user_sid)) {
			sid_compose(&group_sid,
				    get_global_sam_sid(),
				    DOMAIN_RID_USERS);
		} else {
			sid_copy(&domain_sid, &user_sid);
			sid_split_rid(&domain_sid, NULL);
			sid_compose(&group_sid,
				    &domain_sid,
				    DOMAIN_RID_USERS);
		}
	}

	/* Make sure we have a valid group sid */
	is_null = is_null_sid(&group_sid);
	if (is_null) {
		status = NT_STATUS_NO_SUCH_USER;
		goto done;
	}

	/* Construct a netr_SamInfo3 from the information we have */
	info3 = talloc_zero(tmp_ctx, struct netr_SamInfo3);
	if (!info3) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	info3->base.account_name.string = talloc_strdup(info3, unix_username);
	if (info3->base.account_name.string == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	ZERO_STRUCT(domain_sid);

	status = SamInfo3_handle_sids(unix_username,
				&user_sid,
				&group_sid,
				info3,
				&domain_sid,
				extra);

	if (!NT_STATUS_IS_OK(status)) {
		goto done;
	}

	info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
	if (info3->base.domain_sid == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto done;
	}

	ok = sid_peek_check_rid(&domain_sid, &group_sid,
				&info3->base.primary_gid);
	if (!ok) {
		DEBUG(1, ("The primary group domain sid(%s) does not "
			  "match the domain sid(%s) for %s(%s)\n",
			  sid_string_dbg(&group_sid),
			  sid_string_dbg(&domain_sid),
			  unix_username,
			  sid_string_dbg(&user_sid)));
		status = NT_STATUS_INVALID_SID;
		goto done;
	}

	info3->base.acct_flags = ACB_NORMAL;

	if (num_sids) {
		status = group_sids_to_info3(info3, user_sids, num_sids);
		if (!NT_STATUS_IS_OK(status)) {
			goto done;
		}
	}

	*pinfo3 = talloc_steal(mem_ctx, info3);

	status = NT_STATUS_OK;
done:
	talloc_free(tmp_ctx);

	return status;
}
Ejemplo n.º 7
0
#ifdef PCAP_RAW_SOCKETS
/** Build PCAP filter string to pass to libpcap based on listen section
 * Will be called by init_pcap.
 *
 * @param this listen section
 * @return PCAP filter string
 */
static const char *dhcp_pcap_filter_build(rad_listen_t *this)
{
	dhcp_socket_t	*sock = this->data;
	char		*filter;

	/*
	 *	Set the port filter
	 */
	filter = talloc_strdup(this, "(udp and dst port ");
	if (sock->lsock.my_port) {
		filter = talloc_asprintf_append_buffer(filter, "%u)", sock->lsock.my_port);
	} else {
		filter = talloc_strdup_append_buffer(filter, "bootps)");
	}

	if (!fr_ipaddr_is_inaddr_any(&sock->lsock.my_ipaddr)) {
		char buffer[INET_ADDRSTRLEN];
		fr_inet_ntoh(&sock->lsock.my_ipaddr, buffer, sizeof(buffer));

		if (sock->lsock.broadcast) {
			filter = talloc_asprintf_append_buffer(filter, " and (dst host %s or dst host 255.255.255.255)",
							       buffer);
		} else {
			filter = talloc_asprintf_append_buffer(filter, " and dst host %s", buffer);
Ejemplo n.º 8
0
NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, 
				const char *sent_nt_username,
				const char *domain,
				struct auth_serversupplied_info **server_info,
				const struct netr_SamInfo3 *info3)
{
	static const char zeros[16] = {0, };

	NTSTATUS nt_status = NT_STATUS_OK;
	char *found_username = NULL;
	const char *nt_domain;
	const char *nt_username;
	struct dom_sid user_sid;
	struct dom_sid group_sid;
	bool username_was_mapped;
	struct passwd *pwd;
	struct auth_serversupplied_info *result;
	TALLOC_CTX *tmp_ctx = talloc_stackframe();

	/* 
	   Here is where we should check the list of
	   trusted domains, and verify that the SID 
	   matches.
	*/

	if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) {
		nt_status = NT_STATUS_INVALID_PARAMETER;
		goto out;
	}

	if (!sid_compose(&group_sid, info3->base.domain_sid,
			 info3->base.primary_gid)) {
		nt_status = NT_STATUS_INVALID_PARAMETER;
		goto out;
	}

	nt_username = talloc_strdup(tmp_ctx, info3->base.account_name.string);
	if (!nt_username) {
		/* If the server didn't give us one, just use the one we sent
		 * them */
		nt_username = sent_nt_username;
	}

	nt_domain = talloc_strdup(mem_ctx, info3->base.logon_domain.string);
	if (!nt_domain) {
		/* If the server didn't give us one, just use the one we sent
		 * them */
		nt_domain = domain;
	}

	/* If getpwnam() fails try the add user script (2.2.x behavior).

	   We use the _unmapped_ username here in an attempt to provide
	   consistent username mapping behavior between kerberos and NTLM[SSP]
	   authentication in domain mode security.  I.E. Username mapping
	   should be applied to the fully qualified username
	   (e.g. DOMAIN\user) and not just the login name.  Yes this means we
	   called map_username() unnecessarily in make_user_info_map() but
	   that is how the current code is designed.  Making the change here
	   is the least disruptive place.  -- jerry */

	/* this call will try to create the user if necessary */

	nt_status = check_account(tmp_ctx,
				  nt_domain,
				  nt_username,
				  &found_username,
				  &pwd,
				  &username_was_mapped);

	if (!NT_STATUS_IS_OK(nt_status)) {
		/* Handle 'map to guest = Bad Uid */
		if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) &&
		    (lp_security() == SEC_ADS || lp_security() == SEC_DOMAIN) &&
		    lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID) {
			DBG_NOTICE("Try to map %s to guest account",
				   nt_username);
			nt_status = make_server_info_guest(tmp_ctx, &result);
			if (NT_STATUS_IS_OK(nt_status)) {
				*server_info = talloc_move(mem_ctx, &result);
			}
		}
		goto out;
	}

	result = make_server_info(tmp_ctx);
	if (result == NULL) {
		DEBUG(4, ("make_server_info failed!\n"));
		nt_status = NT_STATUS_NO_MEMORY;
		goto out;
	}

	result->unix_name = talloc_strdup(result, found_username);

	/* copy in the info3 */
	result->info3 = copy_netr_SamInfo3(result, info3);
	if (result->info3 == NULL) {
		nt_status = NT_STATUS_NO_MEMORY;
		goto out;
	}

	/* Fill in the unix info we found on the way */

	result->utok.uid = pwd->pw_uid;
	result->utok.gid = pwd->pw_gid;

	/* ensure we are never given NULL session keys */

	if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) {
		result->session_key = data_blob_null;
	} else {
		result->session_key = data_blob_talloc(
			result, info3->base.key.key,
			sizeof(info3->base.key.key));
	}

	if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) {
		result->lm_session_key = data_blob_null;
	} else {
		result->lm_session_key = data_blob_talloc(
			result, info3->base.LMSessKey.key,
			sizeof(info3->base.LMSessKey.key));
	}

	result->nss_token |= username_was_mapped;

	result->guest = (info3->base.user_flags & NETLOGON_GUEST);

	*server_info = talloc_move(mem_ctx, &result);

	nt_status = NT_STATUS_OK;
out:
	talloc_free(tmp_ctx);

	return nt_status;
}
Ejemplo n.º 9
0
NTSTATUS create_local_token(TALLOC_CTX *mem_ctx,
			    const struct auth_serversupplied_info *server_info,
			    DATA_BLOB *session_key,
			    const char *smb_username, /* for ->sanitized_username, for %U subs */
			    struct auth_session_info **session_info_out)
{
	struct security_token *t;
	NTSTATUS status;
	size_t i;
	struct dom_sid tmp_sid;
	struct auth_session_info *session_info;
	struct unixid *ids;
	fstring tmp;

	/* Ensure we can't possible take a code path leading to a
	 * null defref. */
	if (!server_info) {
		return NT_STATUS_LOGON_FAILURE;
	}

	session_info = talloc_zero(mem_ctx, struct auth_session_info);
	if (!session_info) {
		return NT_STATUS_NO_MEMORY;
	}

	session_info->unix_token = talloc_zero(session_info, struct security_unix_token);
	if (!session_info->unix_token) {
		TALLOC_FREE(session_info);
		return NT_STATUS_NO_MEMORY;
	}

	session_info->unix_token->uid = server_info->utok.uid;
	session_info->unix_token->gid = server_info->utok.gid;

	session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix);
	if (!session_info->unix_info) {
		TALLOC_FREE(session_info);
		return NT_STATUS_NO_MEMORY;
	}

	session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name);
	if (!session_info->unix_info->unix_name) {
		TALLOC_FREE(session_info);
		return NT_STATUS_NO_MEMORY;
	}

	/* This is a potentially untrusted username for use in %U */
	alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp));
	session_info->unix_info->sanitized_username =
				talloc_strdup(session_info->unix_info, tmp);

	if (session_key) {
		data_blob_free(&session_info->session_key);
		session_info->session_key = data_blob_talloc(session_info,
								  session_key->data,
								  session_key->length);
		if (!session_info->session_key.data && session_key->length) {
			return NT_STATUS_NO_MEMORY;
		}
	} else {
		session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data,
							      server_info->session_key.length);
	}

	/* We need to populate session_info->info with the information found in server_info->info3 */
	status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base,
					    server_info->guest == false,
					    &session_info->info);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("conversion of info3 into auth_user_info failed!\n"));
		TALLOC_FREE(session_info);
		return status;
	}

	if (server_info->security_token) {
		/* Just copy the token, it has already been finalised
		 * (nasty hack to support a cached guest/system session_info
		 */

		session_info->security_token = dup_nt_token(session_info, server_info->security_token);
		if (!session_info->security_token) {
			TALLOC_FREE(session_info);
			return NT_STATUS_NO_MEMORY;
		}

		session_info->unix_token->ngroups = server_info->utok.ngroups;
		if (server_info->utok.ngroups != 0) {
			session_info->unix_token->groups = (gid_t *)talloc_memdup(
				session_info->unix_token, server_info->utok.groups,
				sizeof(gid_t)*session_info->unix_token->ngroups);
		} else {
			session_info->unix_token->groups = NULL;
		}

		*session_info_out = session_info;
		return NT_STATUS_OK;
	}

	/*
	 * If winbind is not around, we can not make much use of the SIDs the
	 * domain controller provided us with. Likewise if the user name was
	 * mapped to some local unix user.
	 */

	if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) ||
	    (server_info->nss_token)) {
		char *found_username = NULL;
		status = create_token_from_username(session_info,
						    server_info->unix_name,
						    server_info->guest,
						    &session_info->unix_token->uid,
						    &session_info->unix_token->gid,
						    &found_username,
						    &session_info->security_token);
		if (NT_STATUS_IS_OK(status)) {
			session_info->unix_info->unix_name = found_username;
		}
	} else {
		status = create_local_nt_token_from_info3(session_info,
							  server_info->guest,
							  server_info->info3,
							  &server_info->extra,
							  &session_info->security_token);
	}

	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	/* Convert the SIDs to gids. */

	session_info->unix_token->ngroups = 0;
	session_info->unix_token->groups = NULL;

	t = session_info->security_token;

	ids = talloc_array(talloc_tos(), struct unixid,
			   t->num_sids);
	if (ids == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	if (!sids_to_unixids(t->sids, t->num_sids, ids)) {
		TALLOC_FREE(ids);
		return NT_STATUS_NO_MEMORY;
	}

	for (i=0; i<t->num_sids; i++) {

		if (i == 0 && ids[i].type != ID_TYPE_BOTH) {
			continue;
		}

		if (ids[i].type != ID_TYPE_GID &&
		    ids[i].type != ID_TYPE_BOTH) {
			DEBUG(10, ("Could not convert SID %s to gid, "
				   "ignoring it\n",
				   sid_string_dbg(&t->sids[i])));
			continue;
		}
		if (!add_gid_to_array_unique(session_info, ids[i].id,
					     &session_info->unix_token->groups,
					     &session_info->unix_token->ngroups)) {
			return NT_STATUS_NO_MEMORY;
		}
	}

	/*
	 * Add the "Unix Group" SID for each gid to catch mapped groups
	 * and their Unix equivalent.  This is to solve the backwards
	 * compatibility problem of 'valid users = +ntadmin' where
	 * ntadmin has been paired with "Domain Admins" in the group
	 * mapping table.  Otherwise smb.conf would need to be changed
	 * to 'valid user = "******"'.  --jerry
	 *
	 * For consistency we also add the "Unix User" SID,
	 * so that the complete unix token is represented within
	 * the nt token.
	 */

	uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid);

	add_sid_to_array_unique(session_info->security_token, &tmp_sid,
				&session_info->security_token->sids,
				&session_info->security_token->num_sids);

	for ( i=0; i<session_info->unix_token->ngroups; i++ ) {
		gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid);
		add_sid_to_array_unique(session_info->security_token, &tmp_sid,
					&session_info->security_token->sids,
					&session_info->security_token->num_sids);
	}

	security_token_debug(DBGC_AUTH, 10, session_info->security_token);
	debug_unix_user_token(DBGC_AUTH, 10,
			      session_info->unix_token->uid,
			      session_info->unix_token->gid,
			      session_info->unix_token->ngroups,
			      session_info->unix_token->groups);

	status = log_nt_token(session_info->security_token);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	*session_info_out = session_info;
	return NT_STATUS_OK;
}
Ejemplo n.º 10
0
/* This function MUST only used to create the cached server_info for
 * guest.
 *
 * This is a lossy conversion.  Variables known to be lost so far
 * include:
 *
 * - nss_token (not needed because the only read doesn't happen
 * for the GUEST user, as this routine populates ->security_token
 *
 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
 *
 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
 */
static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
									   const struct auth_session_info *src,
									   struct auth_serversupplied_info *server_info)
{
	struct auth_serversupplied_info *dst;

	dst = make_server_info(mem_ctx);
	if (dst == NULL) {
		return NULL;
	}

	/* This element must be provided to convert back to an auth_serversupplied_info */
	SMB_ASSERT(src->unix_info);

	dst->guest = true;
	dst->system = false;

	/* This element must be provided to convert back to an
	 * auth_serversupplied_info.  This needs to be from the
	 * auth_session_info because the group values in particular
	 * may change during create_local_token() processing */
	SMB_ASSERT(src->unix_token);
	dst->utok.uid = src->unix_token->uid;
	dst->utok.gid = src->unix_token->gid;
	dst->utok.ngroups = src->unix_token->ngroups;
	if (src->unix_token->ngroups != 0) {
		dst->utok.groups = (gid_t *)talloc_memdup(
			dst, src->unix_token->groups,
			sizeof(gid_t)*dst->utok.ngroups);
	} else {
		dst->utok.groups = NULL;
	}

	/* We must have a security_token as otherwise the lossy
	 * conversion without nss_token would cause create_local_token
	 * to take the wrong path */
	SMB_ASSERT(src->security_token);

	dst->security_token = dup_nt_token(dst, src->security_token);
	if (!dst->security_token) {
		TALLOC_FREE(dst);
		return NULL;
	}

	dst->session_key = data_blob_talloc( dst, src->session_key.data,
						src->session_key.length);

	/* This is OK because this functions is only used for the
	 * GUEST account, which has all-zero keys for both values */
	dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
						src->session_key.length);

	dst->info3 = copy_netr_SamInfo3(dst, server_info->info3);
	if (!dst->info3) {
		TALLOC_FREE(dst);
		return NULL;
	}

	dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
	if (!dst->unix_name) {
		TALLOC_FREE(dst);
		return NULL;
	}

	return dst;
}
Ejemplo n.º 11
0
struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, const char *domuser,
			     char **p_save_username, bool create )
{
	struct passwd *pw = NULL;
	char *p = NULL;
	char *username = NULL;

	/* we only save a copy of the username it has been mangled 
	   by winbindd use default domain */
	*p_save_username = NULL;

	/* don't call map_username() here since it has to be done higher 
	   up the stack so we don't call it multiple times */

	username = talloc_strdup(mem_ctx, domuser);
	if (!username) {
		return NULL;
	}

	p = strchr_m( username, *lp_winbind_separator() );

	/* code for a DOMAIN\user string */

	if ( p ) {
		pw = Get_Pwnam_alloc( mem_ctx, domuser );
		if ( pw ) {
			/* make sure we get the case of the username correct */
			/* work around 'winbind use default domain = yes' */

			if ( lp_winbind_use_default_domain() &&
			     !strchr_m( pw->pw_name, *lp_winbind_separator() ) ) {
				char *domain;

				/* split the domain and username into 2 strings */
				*p = '\0';
				domain = username;

				*p_save_username = talloc_asprintf(mem_ctx,
								"%s%c%s",
								domain,
								*lp_winbind_separator(),
								pw->pw_name);
				if (!*p_save_username) {
					TALLOC_FREE(pw);
					return NULL;
				}
			} else {
				*p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
			}

			/* whew -- done! */
			return pw;
		}

		/* setup for lookup of just the username */
		/* remember that p and username are overlapping memory */

		p++;
		username = talloc_strdup(mem_ctx, p);
		if (!username) {
			return NULL;
		}
	}

	/* just lookup a plain username */

	pw = Get_Pwnam_alloc(mem_ctx, username);

	/* Create local user if requested but only if winbindd
	   is not running.  We need to protect against cases
	   where winbindd is failing and then prematurely
	   creating users in /etc/passwd */

	if ( !pw && create && !winbind_ping() ) {
		/* Don't add a machine account. */
		if (username[strlen(username)-1] == '$')
			return NULL;

		_smb_create_user(NULL, username, NULL);
		pw = Get_Pwnam_alloc(mem_ctx, username);
	}

	/* one last check for a valid passwd struct */

	if (pw) {
		*p_save_username = talloc_strdup(mem_ctx, pw->pw_name);
	}
	return pw;
}
Ejemplo n.º 12
0
static errno_t sudosrv_get_user(struct sudo_dom_ctx *dctx)
{
    TALLOC_CTX *tmp_ctx = NULL;
    struct sss_domain_info *dom = dctx->domain;
    struct sudo_cmd_ctx *cmd_ctx = dctx->cmd_ctx;
    struct cli_ctx *cli_ctx = dctx->cmd_ctx->cli_ctx;
    struct ldb_result *user;
    time_t cache_expire = 0;
    struct tevent_req *dpreq;
    struct dp_callback_ctx *cb_ctx;
    const char *original_name = NULL;
    char *name = NULL;
    uid_t uid = 0;
    errno_t ret;

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
        return ENOMEM;
    }

    while (dom) {
       /* if it is a domainless search, skip domains that require fully
        * qualified names instead */
        while (dom && cmd_ctx->check_next && dom->fqnames) {
            dom = get_next_domain(dom, false);
        }

        if (!dom) break;

        /* make sure to update the dctx if we changed domain */
        dctx->domain = dom;

        talloc_free(name);
        name = sss_get_cased_name(tmp_ctx, cmd_ctx->username,
                                  dom->case_sensitive);
        if (name == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n"));
            ret = ENOMEM;
            goto done;
        }

        DEBUG(SSSDBG_FUNC_DATA, ("Requesting info about [%s@%s]\n",
              name, dom->name));

        ret = sysdb_getpwnam(dctx, dctx->domain->sysdb,
                             dctx->domain, name, &user);
        if (ret != EOK) {
            DEBUG(SSSDBG_OP_FAILURE,
                  ("Failed to make request to our cache!\n"));
            ret = EIO;
            goto done;
        }

        if (user->count > 1) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  ("getpwnam call returned more than one result !?!\n"));
            ret = EIO;
            goto done;
        }

        if (user->count == 0 && !dctx->check_provider) {
            /* if a multidomain search, try with next */
            if (cmd_ctx->check_next) {
                dctx->check_provider = true;
                dom = get_next_domain(dom, false);
                if (dom) continue;
            }

            DEBUG(SSSDBG_MINOR_FAILURE, ("No results for getpwnam call\n"));
            ret = ENOENT;
            goto done;
        }

        /* One result found, check cache expiry */
        if (user->count == 1) {
            cache_expire = ldb_msg_find_attr_as_uint64(user->msgs[0],
                                                       SYSDB_CACHE_EXPIRE, 0);
        }

        /* If cache miss and we haven't checked DP yet OR the entry is
         * outdated, go to DP */
        if ((user->count == 0 || cache_expire < time(NULL))
            && dctx->check_provider) {
            dpreq = sss_dp_get_account_send(cli_ctx, cli_ctx->rctx,
                                            dom, false, SSS_DP_INITGROUPS,
                                            cmd_ctx->username, 0, NULL);
            if (!dpreq) {
                DEBUG(SSSDBG_CRIT_FAILURE,
                      ("Out of memory sending data provider request\n"));
                ret = ENOMEM;
                goto done;
            }

            cb_ctx = talloc_zero(cli_ctx, struct dp_callback_ctx);
            if(!cb_ctx) {
                talloc_zfree(dpreq);
                ret = ENOMEM;
                goto done;
            }

            cb_ctx->callback = sudosrv_check_user_dp_callback;
            cb_ctx->ptr = dctx;
            cb_ctx->cctx = cli_ctx;
            cb_ctx->mem_ctx = cli_ctx;

            tevent_req_set_callback(dpreq, sudosrv_dp_send_acct_req_done, cb_ctx);

            /* tell caller we are in an async call */
            ret = EAGAIN;
            goto done;
        }

        /* check uid */
        uid = ldb_msg_find_attr_as_int(user->msgs[0], SYSDB_UIDNUM, 0);
        if (uid != cmd_ctx->uid) {
            /* if a multidomain search, try with next */
            if (cmd_ctx->check_next) {
                dctx->check_provider = true;
                dom = get_next_domain(dom, false);
                if (dom) continue;
            }

            DEBUG(SSSDBG_MINOR_FAILURE, ("UID does not match\n"));
            ret = ENOENT;
            goto done;
        }

        /* user is stored in cache, remember cased and original name */
        original_name = ldb_msg_find_attr_as_string(user->msgs[0],
                                                    SYSDB_NAME, NULL);
        if (original_name == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("A user with no name?\n"));
            ret = EFAULT;
            goto done;
        }

        cmd_ctx->cased_username = talloc_move(cmd_ctx, &name);
        cmd_ctx->orig_username = talloc_strdup(cmd_ctx, original_name);
        if (cmd_ctx->orig_username == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, ("Out of memory\n"));
            ret = ENOMEM;
            goto done;
        }

        /* and set domain */
        cmd_ctx->domain = dom;

        DEBUG(SSSDBG_TRACE_FUNC, ("Returning info for user [%s@%s]\n",
              cmd_ctx->username, dctx->domain->name));
        ret = EOK;
        goto done;
    }
Ejemplo n.º 13
0
/*
  parse a binding string into a dcerpc_binding structure
*/
_PUBLIC_ NTSTATUS dcerpc_parse_binding(TALLOC_CTX *mem_ctx, const char *_s, struct dcerpc_binding **b_out)
{
	char *_t;
	struct dcerpc_binding *b;
	char *s;
	char *options = NULL;
	char *p;
	size_t i;
	NTSTATUS status;

	b = talloc_zero(mem_ctx, struct dcerpc_binding);
	if (!b) {
		return NT_STATUS_NO_MEMORY;
	}

	_t = talloc_strdup(b, _s);
	if (_t == NULL) {
		talloc_free(b);
		return NT_STATUS_NO_MEMORY;
	}

	s = _t;

	p = strchr(s, '[');
	if (p) {
		*p = '\0';
		options = p + 1;
		if (options[strlen(options)-1] != ']') {
			talloc_free(b);
			return NT_STATUS_INVALID_PARAMETER_MIX;
		}
		options[strlen(options)-1] = 0;
	}

	p = strchr(s, '@');

	if (p && PTR_DIFF(p, s) == 36) { /* 36 is the length of a UUID */
		*p = '\0';

		status = dcerpc_binding_set_string_option(b, "object", s);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(b);
			return status;
		}

		s = p + 1;
	}

	p = strchr(s, ':');

	if (p == NULL) {
		b->transport = NCA_UNKNOWN;
	} else if (is_ipaddress_v6(s)) {
		b->transport = NCA_UNKNOWN;
	} else {
		*p = '\0';

		status = dcerpc_binding_set_string_option(b, "transport", s);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(b);
			return status;
		}

		s = p + 1;
	}

	if (strlen(s) > 0) {
		status = dcerpc_binding_set_string_option(b, "host", s);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(b);
			return status;
		}

		b->target_hostname = talloc_strdup(b, b->host);
		if (b->target_hostname == NULL) {
			talloc_free(b);
			return NT_STATUS_NO_MEMORY;
		}
	}

	for (i=0; options != NULL; i++) {
		const char *name = options;
		const char *value = NULL;

		p = strchr(options, ',');
		if (p != NULL) {
			*p = '\0';
			options = p+1;
		} else {
			options = NULL;
		}

		p = strchr(name, '=');
		if (p != NULL) {
			*p = '\0';
			value = p + 1;
		}

		if (value == NULL) {
			/*
			 * If it's not a key=value pair
			 * it might be a ncacn_option
			 * or if it's the first option
			 * it's the endpoint.
			 */
			const struct ncacn_option *no = NULL;

			value = name;

			no = ncacn_option_by_name(name);
			if (no == NULL) {
				if (i > 0) {
					/*
					 * we don't allow unknown options
					 */
					return NT_STATUS_INVALID_PARAMETER_MIX;
				}

				/*
				 * This is the endpoint
				 */
				name = "endpoint";
				if (strlen(value) == 0) {
					value = NULL;
				}
			}
		}

		status = dcerpc_binding_set_string_option(b, name, value);
		if (!NT_STATUS_IS_OK(status)) {
			talloc_free(b);
			return status;
		}
	}

	talloc_free(_t);
	*b_out = b;
	return NT_STATUS_OK;
}
Ejemplo n.º 14
0
/*
  form a binding string from a binding structure
*/
_PUBLIC_ char *dcerpc_binding_string(TALLOC_CTX *mem_ctx, const struct dcerpc_binding *b)
{
	char *s = talloc_strdup(mem_ctx, "");
	char *o = s;
	int i;
	const char *t_name = NULL;
	bool option_section = false;
	const char *target_hostname = NULL;

	if (b->transport != NCA_UNKNOWN) {
		t_name = derpc_transport_string_by_transport(b->transport);
		if (!t_name) {
			talloc_free(o);
			return NULL;
		}
	}

	if (!GUID_all_zero(&b->object)) {
		o = s;
		s = talloc_asprintf_append_buffer(s, "%s@",
				    GUID_string(mem_ctx, &b->object));
		if (s == NULL) {
			talloc_free(o);
			return NULL;
		}
	}

	if (t_name != NULL) {
		o = s;
		s = talloc_asprintf_append_buffer(s, "%s:", t_name);
		if (s == NULL) {
			talloc_free(o);
			return NULL;
		}
	}

	if (b->host) {
		o = s;
		s = talloc_asprintf_append_buffer(s, "%s", b->host);
		if (s == NULL) {
			talloc_free(o);
			return NULL;
		}
	}

	target_hostname = b->target_hostname;
	if (target_hostname != NULL && b->host != NULL) {
		if (strcmp(target_hostname, b->host) == 0) {
			target_hostname = NULL;
		}
	}

	if (b->endpoint) {
		option_section = true;
	} else if (target_hostname) {
		option_section = true;
	} else if (b->target_principal) {
		option_section = true;
	} else if (b->assoc_group_id != 0) {
		option_section = true;
	} else if (b->options) {
		option_section = true;
	} else if (b->flags) {
		option_section = true;
	}

	if (!option_section) {
		return s;
	}

	o = s;
	s = talloc_asprintf_append_buffer(s, "[");
	if (s == NULL) {
		talloc_free(o);
		return NULL;
	}

	if (b->endpoint) {
		o = s;
		s = talloc_asprintf_append_buffer(s, "%s", b->endpoint);
		if (s == NULL) {
			talloc_free(o);
			return NULL;
		}
	}

	for (i=0;i<ARRAY_SIZE(ncacn_options);i++) {
		if (!(b->flags & ncacn_options[i].flag)) {
			continue;
		}

		o = s;
		s = talloc_asprintf_append_buffer(s, ",%s", ncacn_options[i].name);
		if (s == NULL) {
			talloc_free(o);
			return NULL;
		}
	}

	if (target_hostname) {
		o = s;
		s = talloc_asprintf_append_buffer(s, ",target_hostname=%s",
						  b->target_hostname);
		if (s == NULL) {
			talloc_free(o);
			return NULL;
		}
	}

	if (b->target_principal) {
		o = s;
		s = talloc_asprintf_append_buffer(s, ",target_principal=%s",
						  b->target_principal);
		if (s == NULL) {
			talloc_free(o);
			return NULL;
		}
	}

	if (b->assoc_group_id != 0) {
		o = s;
		s = talloc_asprintf_append_buffer(s, ",assoc_group_id=0x%08x",
						  b->assoc_group_id);
		if (s == NULL) {
			talloc_free(o);
			return NULL;
		}
	}

	for (i=0;b->options && b->options[i];i++) {
		o = s;
		s = talloc_asprintf_append_buffer(s, ",%s", b->options[i]);
		if (s == NULL) {
			talloc_free(o);
			return NULL;
		}
	}

	o = s;
	s = talloc_asprintf_append_buffer(s, "]");
	if (s == NULL) {
		talloc_free(o);
		return NULL;
	}

	return s;
}
Ejemplo n.º 15
0
/*
 *	%{poke:sql.foo=bar}
 */
static ssize_t xlat_poke(UNUSED void *instance, REQUEST *request,
			 char const *fmt, char *out, size_t outlen)
{
	int i;
	void *data, *base;
	char *p, *q;
	module_instance_t *mi;
	char *buffer;
	CONF_SECTION *modules;
	CONF_PAIR *cp;
	CONF_PARSER const *variables;
	size_t len;

	rad_assert(outlen > 1);
	rad_assert(request != NULL);
	rad_assert(fmt != NULL);
	rad_assert(out != NULL);

	*out = '\0';

	modules = cf_section_sub_find(request->root->config, "modules");
	if (!modules) return 0;

	buffer = talloc_strdup(request, fmt);
	if (!buffer) return 0;

	p = strchr(buffer, '.');
	if (!p) return 0;

	*(p++) = '\0';

	mi = module_find(modules, buffer);
	if (!mi) {
		RDEBUG("Failed finding module '%s'", buffer);
	fail:
		talloc_free(buffer);
		return 0;
	}

	q = strchr(p, '=');
	if (!q) {
		RDEBUG("Failed finding '=' in string '%s'", fmt);
		goto fail;
	}

	*(q++) = '\0';

	if (strchr(p, '.') != NULL) {
		RDEBUG("Can't do sub-sections right now");
		goto fail;
	}

	cp = cf_pair_find(mi->cs, p);
	if (!cp) {
		RDEBUG("No such item '%s'", p);
		goto fail;
	}

	/*
	 *	Copy the old value to the output buffer, that way
	 *	tests can restore it later, if they need to.
	 */
	len = strlcpy(out, cf_pair_value(cp), outlen);

	if (cf_pair_replace(mi->cs, cp, q) < 0) {
		RDEBUG("Failed replacing pair");
		goto fail;
	}

	base = mi->insthandle;
	variables = mi->entry->module->config;

	/*
	 *	Handle the known configuration parameters.
	 */
	for (i = 0; variables[i].name != NULL; i++) {
		int ret;

		if (variables[i].type == PW_TYPE_SUBSECTION) continue;
		/* else it's a CONF_PAIR */

		/*
		 *	Not the pair we want.  Skip it.
		 */
		if (strcmp(variables[i].name, p) != 0) continue;

		if (variables[i].data) {
			data = variables[i].data; /* prefer this. */
		} else if (base) {
			data = ((char *)base) + variables[i].offset;
		} else {
			DEBUG2("Internal sanity check 2 failed in cf_section_parse");
			goto fail;
		}

		/*
		 *	Parse the pair we found, or a default value.
		 */
		ret = cf_item_parse(mi->cs, variables[i].name, variables[i].type, data, variables[i].dflt);
		if (ret < 0) {
			DEBUG2("Failed inserting new value into module instance data");
			goto fail;
		}
		break;		/* we found it, don't do any more */
	}

	talloc_free(buffer);

	return len;
}
Ejemplo n.º 16
0
/*
 *  Do chroot, if requested.
 *
 *  Switch UID and GID to what is specified in the config file
 */
static int switch_users(CONF_SECTION *cs)
{
	bool do_suid = false;
	bool do_sgid = false;

	/*
	 *	Get the current maximum for core files.  Do this
	 *	before anything else so as to ensure it's properly
	 *	initialized.
	 */
	if (fr_set_dumpable_init() < 0) {
		fr_perror("radiusd");
		return 0;
	}

	/*
	 *	Don't do chroot/setuid/setgid if we're in debugging
	 *	as non-root.
	 */
	if (rad_debug_lvl && (getuid() != 0)) return 1;

	if (cf_section_parse(cs, NULL, bootstrap_config) < 0) {
		fprintf(stderr, "radiusd: Error: Failed to parse user/group information.\n");
		return 0;
	}

#ifdef HAVE_GRP_H
	/*
	 *	Get the correct GID for the server.
	 */
	server_gid = getgid();

	if (gid_name) {
		struct group *gr;

		gr = getgrnam(gid_name);
		if (!gr) {
			fprintf(stderr, "%s: Cannot get ID for group %s: %s\n",
				progname, gid_name, fr_syserror(errno));
			return 0;
		}

		if (server_gid != gr->gr_gid) {
			server_gid = gr->gr_gid;
			do_sgid = true;
		}
	}
#endif

	/*
	 *	Get the correct UID for the server.
	 */
	server_uid = getuid();

	if (uid_name) {
		struct passwd *user;

		if (rad_getpwnam(cs, &user, uid_name) < 0) {
			fprintf(stderr, "%s: Cannot get passwd entry for user %s: %s\n",
				progname, uid_name, fr_strerror());
			return 0;
		}

		/*
		 *	We're not the correct user.  Go set that.
		 */
		if (server_uid != user->pw_uid) {
			server_uid = user->pw_uid;
			do_suid = true;
#ifdef HAVE_INITGROUPS
			if (initgroups(uid_name, server_gid) < 0) {
				fprintf(stderr, "%s: Cannot initialize supplementary group list for user %s: %s\n",
					progname, uid_name, fr_syserror(errno));
				talloc_free(user);
				return 0;
			}
#endif
		}

		talloc_free(user);
	}

	/*
	 *	Do chroot BEFORE changing UIDs.
	 */
	if (chroot_dir) {
		if (chroot(chroot_dir) < 0) {
			fprintf(stderr, "%s: Failed to perform chroot %s: %s",
				progname, chroot_dir, fr_syserror(errno));
			return 0;
		}

		/*
		 *	Note that we leave chdir alone.  It may be
		 *	OUTSIDE of the root.  This allows us to read
		 *	the configuration from "-d ./etc/raddb", with
		 *	the chroot as "./chroot/" for example.  After
		 *	the server has been loaded, it does a "cd
		 *	${logdir}" below, so that core files (if any)
		 *	go to a logging directory.
		 *
		 *	This also allows the configuration of the
		 *	server to be outside of the chroot.  If the
		 *	server is statically linked, then the only
		 *	things needed inside of the chroot are the
		 *	logging directories.
		 */
	}

#ifdef HAVE_GRP_H
	/*
	 *	Set the GID.  Don't bother checking it.
	 */
	if (do_sgid) {
		if (setgid(server_gid) < 0){
			fprintf(stderr, "%s: Failed setting group to %s: %s",
				progname, gid_name, fr_syserror(errno));
			return 0;
		}
	}
#endif

	/*
	 *	The directories for PID files and logs must exist.  We
	 *	need to create them if we're told to write files to
	 *	those directories.
	 *
	 *	Because this creation is new in 3.0.9, it's a soft
	 *	fail.
	 *
	 */
	if (main_config.write_pid) {
		char *my_dir;

		my_dir = talloc_strdup(NULL, run_dir);
		if (rad_mkdir(my_dir, 0750, server_uid, server_gid) < 0) {
			DEBUG("Failed to create run_dir %s: %s",
			      my_dir, strerror(errno));
		}
		talloc_free(my_dir);
	}

	if (default_log.dst == L_DST_FILES) {
		char *my_dir;

		my_dir = talloc_strdup(NULL, radlog_dir);
		if (rad_mkdir(my_dir, 0750, server_uid, server_gid) < 0) {
			DEBUG("Failed to create logdir %s: %s",
			      my_dir, strerror(errno));
		}
		talloc_free(my_dir);
	}

	/*
	 *	Once we're done with all of the privileged work,
	 *	permanently change the UID.
	 */
	if (do_suid) {
		rad_suid_set_down_uid(server_uid);
		rad_suid_down();
	}

	/*
	 *	If we don't already have a log file open, open one
	 *	now.  We may not have been logging anything yet.  The
	 *	server normally starts up fairly quietly.
	 */
	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));
			return 0;
		}
	}

	/*
	 *	If we need to change UID, ensure that the log files
	 *	have the correct owner && group.
	 *
	 *	We have to do this because some log files MAY already
	 *	have been written as root.  We need to change them to
	 *	have the correct ownership before proceeding.
	 */
	if ((do_suid || do_sgid) &&
	    (default_log.dst == L_DST_FILES)) {
		if (fchown(default_log.fd, server_uid, server_gid) < 0) {
			fprintf(stderr, "%s: Cannot change ownership of log file %s: %s\n",
				progname, main_config.log_file, fr_syserror(errno));
			return 0;
		}
	}

	/*
	 *	This also clears the dumpable flag if core dumps
	 *	aren't allowed.
	 */
	if (fr_set_dumpable(allow_core_dumps) < 0) {
		ERROR("%s", fr_strerror());
	}

	if (allow_core_dumps) {
		INFO("Core dumps are enabled");
	}

	return 1;
}
Ejemplo n.º 17
0
NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
			  struct samu *samu,
			  const char *login_server,
			  struct netr_SamInfo3 **_info3,
			  struct extra_auth_info *extra)
{
	struct netr_SamInfo3 *info3;
	const struct dom_sid *user_sid;
	const struct dom_sid *group_sid;
	struct dom_sid domain_sid;
	struct dom_sid *group_sids;
	uint32_t num_group_sids = 0;
	const char *tmp;
	gid_t *gids;
	NTSTATUS status;

	user_sid = pdb_get_user_sid(samu);
	group_sid = pdb_get_group_sid(samu);

	if (!user_sid || !group_sid) {
		DEBUG(1, ("Sam account is missing sids!\n"));
		return NT_STATUS_UNSUCCESSFUL;
	}

	info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
	if (!info3) {
		return NT_STATUS_NO_MEMORY;
	}

	ZERO_STRUCT(domain_sid);

	status = SamInfo3_handle_sids(pdb_get_username(samu),
				user_sid,
				group_sid,
				info3,
				&domain_sid,
				extra);

	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(info3);
		return status;
	}

	unix_to_nt_time(&info3->base.logon_time, pdb_get_logon_time(samu));
	unix_to_nt_time(&info3->base.logoff_time, get_time_t_max());
	unix_to_nt_time(&info3->base.kickoff_time, get_time_t_max());
	unix_to_nt_time(&info3->base.last_password_change,
			pdb_get_pass_last_set_time(samu));
	unix_to_nt_time(&info3->base.allow_password_change,
			pdb_get_pass_can_change_time(samu));
	unix_to_nt_time(&info3->base.force_password_change,
			pdb_get_pass_must_change_time(samu));

	tmp = pdb_get_username(samu);
	if (tmp) {
		info3->base.account_name.string	= talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.account_name.string);
	}
	tmp = pdb_get_fullname(samu);
	if (tmp) {
		info3->base.full_name.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.full_name.string);
	}
	tmp = pdb_get_logon_script(samu);
	if (tmp) {
		info3->base.logon_script.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.logon_script.string);
	}
	tmp = pdb_get_profile_path(samu);
	if (tmp) {
		info3->base.profile_path.string	= talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.profile_path.string);
	}
	tmp = pdb_get_homedir(samu);
	if (tmp) {
		info3->base.home_directory.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.home_directory.string);
	}
	tmp = pdb_get_dir_drive(samu);
	if (tmp) {
		info3->base.home_drive.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.home_drive.string);
	}

	info3->base.logon_count	= pdb_get_logon_count(samu);
	info3->base.bad_password_count = pdb_get_bad_password_count(samu);

	info3->base.logon_domain.string = talloc_strdup(info3,
						  pdb_get_domain(samu));
	RET_NOMEM(info3->base.logon_domain.string);

	info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
	RET_NOMEM(info3->base.domain_sid);

	status = pdb_enum_group_memberships(mem_ctx, samu,
					    &group_sids, &gids,
					    &num_group_sids);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to get groups from sam account.\n"));
		TALLOC_FREE(info3);
		return status;
	}

	if (num_group_sids) {
		status = group_sids_to_info3(info3, group_sids, num_group_sids);
		if (!NT_STATUS_IS_OK(status)) {
			TALLOC_FREE(info3);
			return status;
		}
	}

	/* We don't need sids and gids after the conversion */
	TALLOC_FREE(group_sids);
	TALLOC_FREE(gids);
	num_group_sids = 0;

	/* FIXME: should we add other flags ? */
	info3->base.user_flags = NETLOGON_EXTRA_SIDS;

	if (login_server) {
		info3->base.logon_server.string = talloc_strdup(info3, login_server);
		RET_NOMEM(info3->base.logon_server.string);
	}

	info3->base.acct_flags = pdb_get_acct_ctrl(samu);

	*_info3 = info3;
	return NT_STATUS_OK;
}
Ejemplo n.º 18
0
bool torture_domain_close_samr(struct torture_context *torture)
{
	bool ret = true;
	NTSTATUS status;
	TALLOC_CTX *mem_ctx = NULL;
	struct libnet_context *ctx;
	struct lsa_String domain_name;
	struct dcerpc_binding *binding;
	uint32_t access_mask;
	struct policy_handle h;
	struct dcerpc_pipe *p;
	struct libnet_DomainClose r;
	struct dom_sid *sid;

	status = torture_rpc_binding(torture, &binding);
	if (!NT_STATUS_IS_OK(status)) {
		return false;
	}

	ctx = libnet_context_init(torture->ev, torture->lp_ctx);
	if (ctx == NULL) {
		torture_comment(torture, "failed to create libnet context\n");
		ret = false;
		goto done;
	}

	ctx->cred = cmdline_credentials;

	mem_ctx = talloc_init("torture_domain_close_samr");
	status = dcerpc_pipe_connect_b(mem_ctx, &p, binding, &ndr_table_samr,
				     ctx->cred, torture->ev, torture->lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		torture_comment(torture, "failed to connect to server: %s\n", nt_errstr(status));
		ret = false;
		goto done;
	}

	domain_name.string = talloc_strdup(mem_ctx, lpcfg_workgroup(torture->lp_ctx));

	if (!test_opendomain_samr(torture, p->binding_handle, torture, &h, &domain_name, &access_mask, &sid)) {
		torture_comment(torture, "failed to open domain on samr service\n");
		ret = false;
		goto done;
	}

	ctx->samr.pipe        = p;
	ctx->samr.name        = talloc_steal(ctx, domain_name.string);
	ctx->samr.access_mask = access_mask;
	ctx->samr.handle      = h;
	ctx->samr.sid         = talloc_steal(ctx, sid);

	ZERO_STRUCT(r);
	r.in.type = DOMAIN_SAMR;
	r.in.domain_name = domain_name.string;

	status = libnet_DomainClose(ctx, mem_ctx, &r);
	if (!NT_STATUS_IS_OK(status)) {
		ret = false;
		goto done;
	}

done:
	talloc_free(mem_ctx);
	talloc_free(ctx);
	return ret;
}
Ejemplo n.º 19
0
static char *sdap_sudo_build_host_filter(TALLOC_CTX *mem_ctx,
                                         struct sdap_attr_map *map,
                                         char **hostnames,
                                         char **ip_addr,
                                         bool netgroups,
                                         bool regexp)
{
    TALLOC_CTX *tmp_ctx = NULL;
    char *filter = NULL;
    int i;

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, ("talloc_new() failed\n"));
        return NULL;
    }

    filter = talloc_strdup(tmp_ctx, "(|");
    if (filter == NULL) {
        goto done;
    }

    /* ALL */
    filter = talloc_asprintf_append_buffer(filter, "(%s=ALL)",
                                           map[SDAP_AT_SUDO_HOST].name);
    if (filter == NULL) {
        goto done;
    }

    /* hostnames */
    if (hostnames != NULL) {
        for (i = 0; hostnames[i] != NULL; i++) {
            filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
                                                   map[SDAP_AT_SUDO_HOST].name,
                                                   hostnames[i]);
            if (filter == NULL) {
                goto done;
            }
        }
    }

    /* ip addresses and networks */
    if (ip_addr != NULL) {
        for (i = 0; ip_addr[i] != NULL; i++) {
            filter = talloc_asprintf_append_buffer(filter, "(%s=%s)",
                                                   map[SDAP_AT_SUDO_HOST].name,
                                                   ip_addr[i]);
            if (filter == NULL) {
                goto done;
            }
        }
    }

    /* sudoHost contains netgroup - will be filtered more by sudo */
    if (netgroups) {
        filter = talloc_asprintf_append_buffer(filter, SDAP_SUDO_FILTER_NETGROUP,
                                               map[SDAP_AT_SUDO_HOST].name,
                                               "*");
        if (filter == NULL) {
            goto done;
        }
    }

    /* sudoHost contains regexp - will be filtered more by sudo */
    /* from sudo match.c :
     * #define has_meta(s)  (strpbrk(s, "\\?*[]") != NULL)
     */
    if (regexp) {
        filter = talloc_asprintf_append_buffer(filter,
                                               "(|(%s=*\\\\*)(%s=*?*)(%s=*\\**)"
                                                 "(%s=*[*]*))",
                                               map[SDAP_AT_SUDO_HOST].name,
                                               map[SDAP_AT_SUDO_HOST].name,
                                               map[SDAP_AT_SUDO_HOST].name,
                                               map[SDAP_AT_SUDO_HOST].name);
        if (filter == NULL) {
            goto done;
        }
    }

    filter = talloc_strdup_append_buffer(filter, ")");
    if (filter == NULL) {
        goto done;
    }

    talloc_steal(mem_ctx, filter);

done:
    talloc_free(tmp_ctx);

    return filter;
}
Ejemplo n.º 20
0
static char *
build_filter(TALLOC_CTX *mem_ctx,
             struct sysdb_ctx *sysdb,
             hash_table_t *table,
             struct sdap_attr_map *map,
             ipa_sudo_conv_rdn_fn rdn_fn)
{
    TALLOC_CTX *tmp_ctx;
    hash_key_t *keys;
    unsigned long int count;
    unsigned long int i;
    char *filter;
    char *rdn_val;
    const char *rdn_attr;
    char *safe_rdn;
    errno_t ret;
    int hret;

    tmp_ctx = talloc_new(NULL);
    if (tmp_ctx == NULL) {
        return NULL;
    }

    hret = hash_keys(table, &count, &keys);
    if (hret != HASH_SUCCESS) {
        ret = ENOMEM;
        goto done;
    }

    talloc_steal(tmp_ctx, keys);

    filter = talloc_strdup(tmp_ctx, "");
    if (filter == NULL) {
        ret = ENOMEM;
        goto done;
    }

    for (i = 0; i < count; i++) {
        ret = rdn_fn(tmp_ctx, map, sysdb, keys[i].str, &rdn_val, &rdn_attr);
        if (ret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get member %s [%d]: %s\n",
                  keys[i].str, ret, sss_strerror(ret));
            goto done;
        }

        ret = sss_filter_sanitize(tmp_ctx, rdn_val, &safe_rdn);
        if (ret != EOK) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Unable to sanitize DN "
                  "[%d]: %s\n", ret, sss_strerror(ret));
            goto done;
        }

        filter = talloc_asprintf_append(filter, "(%s=%s)", rdn_attr, safe_rdn);
        if (filter == NULL) {
            ret = ENOMEM;
            goto done;
        }
    }

    /* objectClass is always first */
    filter = talloc_asprintf(filter, "(&(objectClass=%s)(|%s))",
                             map[0].name, filter);
    if (filter == NULL) {
        ret = ENOMEM;
        goto done;
    }

    talloc_steal(mem_ctx, filter);

    ret = EOK;

done:
    talloc_free(tmp_ctx);

    if (ret != EOK) {
        return NULL;
    }

    return filter;
}
Ejemplo n.º 21
0
/*
 * do a domain join using DCERPC/SAMR calls
 * - connect to the LSA pipe, to try and find out information about the domain
 * - create a secondary connection to SAMR pipe
 * - do a samr_Connect to get a policy handle
 * - do a samr_LookupDomain to get the domain sid
 * - do a samr_OpenDomain to get a domain handle
 * - do a samr_CreateAccount to try and get a new account 
 * 
 * If that fails, do:
 * - do a samr_LookupNames to get the users rid
 * - do a samr_OpenUser to get a user handle
 * - potentially delete and recreate the user
 * - assert the account is of the right type with samrQueryUserInfo
 * 
 * - call libnet_SetPassword_samr_handle to set the password,
 *   and pass a samr_UserInfo21 struct to set full_name and the account flags
 *
 * - do some ADS specific things when we join as Domain Controller,
 *    look at libnet_joinADSDomain() for the details
 */
NTSTATUS libnet_JoinDomain(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, struct libnet_JoinDomain *r)
{
	TALLOC_CTX *tmp_ctx;

	NTSTATUS status, cu_status;

	struct libnet_RpcConnect *connect_with_info;
	struct dcerpc_pipe *samr_pipe;

	struct samr_Connect sc;
	struct policy_handle p_handle;
	struct samr_OpenDomain od;
	struct policy_handle d_handle;
	struct samr_LookupNames ln;
	struct samr_Ids rids, types;
	struct samr_OpenUser ou;
	struct samr_CreateUser2 cu;
	struct policy_handle *u_handle = NULL;
	struct samr_QueryUserInfo qui;
	union samr_UserInfo *uinfo;
	struct samr_UserInfo21 u_info21;
	union libnet_SetPassword r2;
	struct samr_GetUserPwInfo pwp;
	struct samr_PwInfo info;
	struct lsa_String samr_account_name;
	
	uint32_t acct_flags, old_acct_flags;
	uint32_t rid, access_granted;
	int policy_min_pw_len = 0;

	struct dom_sid *account_sid = NULL;
	const char *password_str = NULL;
	
	r->out.error_string = NULL;
	r2.samr_handle.out.error_string = NULL;
	
	tmp_ctx = talloc_named(mem_ctx, 0, "libnet_Join temp context");
	if (!tmp_ctx) {
		r->out.error_string = NULL;
		return NT_STATUS_NO_MEMORY;
	}
	
	u_handle = talloc(tmp_ctx, struct policy_handle);
	if (!u_handle) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}
	
	connect_with_info = talloc_zero(tmp_ctx, struct libnet_RpcConnect);
	if (!connect_with_info) {
		r->out.error_string = NULL;
		talloc_free(tmp_ctx);
		return NT_STATUS_NO_MEMORY;
	}

	/* prepare connect to the SAMR pipe of PDC */
	if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) {
		connect_with_info->in.binding = NULL;
		connect_with_info->in.name    = r->in.domain_name;
	} else {
		connect_with_info->in.binding = r->in.binding;
		connect_with_info->in.name    = NULL;
	}

	/* This level makes a connection to the LSA pipe on the way,
	 * to get some useful bits of information about the domain */
	connect_with_info->level              = LIBNET_RPC_CONNECT_DC_INFO;
	connect_with_info->in.dcerpc_iface    = &ndr_table_samr;

	/*
	  establish the SAMR connection
	*/
	status = libnet_RpcConnect(ctx, tmp_ctx, connect_with_info);
	if (!NT_STATUS_IS_OK(status)) {
		if (r->in.binding) {
			r->out.error_string = talloc_asprintf(mem_ctx,
							      "Connection to SAMR pipe of DC %s failed: %s",
							      r->in.binding, connect_with_info->out.error_string);
		} else {
			r->out.error_string = talloc_asprintf(mem_ctx,
							      "Connection to SAMR pipe of PDC for %s failed: %s",
							      r->in.domain_name, connect_with_info->out.error_string);
		}
		talloc_free(tmp_ctx);
		return status;
	}

	samr_pipe = connect_with_info->out.dcerpc_pipe;

	status = dcerpc_pipe_auth(tmp_ctx, &samr_pipe,
				  connect_with_info->out.dcerpc_pipe->binding, 
				  &ndr_table_samr, ctx->cred, ctx->lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		r->out.error_string = talloc_asprintf(mem_ctx,
						"SAMR bind failed: %s",
						nt_errstr(status));
		talloc_free(tmp_ctx);
		return status;
	}

	/* prepare samr_Connect */
	ZERO_STRUCT(p_handle);
	sc.in.system_name = NULL;
	sc.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	sc.out.connect_handle = &p_handle;

	/* 2. do a samr_Connect to get a policy handle */
	status = dcerpc_samr_Connect_r(samr_pipe->binding_handle, tmp_ctx, &sc);
	if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(sc.out.result)) {
		status = sc.out.result;
	}
	if (!NT_STATUS_IS_OK(status)) {
		r->out.error_string = talloc_asprintf(mem_ctx,
						"samr_Connect failed: %s",
						nt_errstr(status));
		talloc_free(tmp_ctx);
		return status;
	}

	/* If this is a connection on ncacn_ip_tcp to Win2k3 SP1, we don't get back this useful info */
	if (!connect_with_info->out.domain_name) {
		if (r->in.level == LIBNET_JOINDOMAIN_AUTOMATIC) {
			connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, r->in.domain_name);
		} else {
			/* Bugger, we just lost our way to automatically find the domain name */
			connect_with_info->out.domain_name = talloc_strdup(tmp_ctx, lpcfg_workgroup(ctx->lp_ctx));
			connect_with_info->out.realm = talloc_strdup(tmp_ctx, lpcfg_realm(ctx->lp_ctx));
		}
	}

	/* Perhaps we didn't get a SID above, because we are against ncacn_ip_tcp */
	if (!connect_with_info->out.domain_sid) {
		struct lsa_String name;
		struct samr_LookupDomain l;
		struct dom_sid2 *sid = NULL;
		name.string = connect_with_info->out.domain_name;
		l.in.connect_handle = &p_handle;
		l.in.domain_name = &name;
		l.out.sid = &sid;
		
		status = dcerpc_samr_LookupDomain_r(samr_pipe->binding_handle, tmp_ctx, &l);
		if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(l.out.result)) {
			status = l.out.result;
		}
		if (!NT_STATUS_IS_OK(status)) {
			r->out.error_string = talloc_asprintf(mem_ctx,
							      "SAMR LookupDomain failed: %s",
							      nt_errstr(status));
			talloc_free(tmp_ctx);
			return status;
		}
		connect_with_info->out.domain_sid = *l.out.sid;
	}

	/* prepare samr_OpenDomain */
	ZERO_STRUCT(d_handle);
	od.in.connect_handle = &p_handle;
	od.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
	od.in.sid = connect_with_info->out.domain_sid;
	od.out.domain_handle = &d_handle;

	/* do a samr_OpenDomain to get a domain handle */
	status = dcerpc_samr_OpenDomain_r(samr_pipe->binding_handle, tmp_ctx, &od);
	if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(od.out.result)) {
		status = od.out.result;
	}
	if (!NT_STATUS_IS_OK(status)) {
		r->out.error_string = talloc_asprintf(mem_ctx,
						      "samr_OpenDomain for [%s] failed: %s",
						      dom_sid_string(tmp_ctx, connect_with_info->out.domain_sid),
						      nt_errstr(status));
		talloc_free(tmp_ctx);
		return status;
	}
	
	/* prepare samr_CreateUser2 */
	ZERO_STRUCTP(u_handle);
	cu.in.domain_handle  = &d_handle;
	cu.in.access_mask     = SEC_FLAG_MAXIMUM_ALLOWED;
	samr_account_name.string = r->in.account_name;
	cu.in.account_name    = &samr_account_name;
	cu.in.acct_flags      = r->in.acct_type;
	cu.out.user_handle    = u_handle;
	cu.out.rid            = &rid;
	cu.out.access_granted = &access_granted;

	/* do a samr_CreateUser2 to get an account handle, or an error */
	cu_status = dcerpc_samr_CreateUser2_r(samr_pipe->binding_handle, tmp_ctx, &cu);
	if (NT_STATUS_IS_OK(cu_status) && !NT_STATUS_IS_OK(cu.out.result)) {
		cu_status = cu.out.result;
	}
	status = cu_status;
	if (NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) {
		/* prepare samr_LookupNames */
		ln.in.domain_handle = &d_handle;
		ln.in.num_names = 1;
		ln.in.names = talloc_array(tmp_ctx, struct lsa_String, 1);
		ln.out.rids = &rids;
		ln.out.types = &types;
		if (!ln.in.names) {
			r->out.error_string = NULL;
			talloc_free(tmp_ctx);
			return NT_STATUS_NO_MEMORY;
		}
		ln.in.names[0].string = r->in.account_name;
		
		/* 5. do a samr_LookupNames to get the users rid */
		status = dcerpc_samr_LookupNames_r(samr_pipe->binding_handle, tmp_ctx, &ln);
		if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ln.out.result)) {
			status = ln.out.result;
		}
		if (!NT_STATUS_IS_OK(status)) {
			r->out.error_string = talloc_asprintf(mem_ctx,
						"samr_LookupNames for [%s] failed: %s",
						r->in.account_name,
						nt_errstr(status));
			talloc_free(tmp_ctx);
			return status;
		}
		
		/* check if we got one RID for the user */
		if (ln.out.rids->count != 1) {
			r->out.error_string = talloc_asprintf(mem_ctx,
							      "samr_LookupNames for [%s] returns %d RIDs",
							      r->in.account_name, ln.out.rids->count);
			talloc_free(tmp_ctx);
			return NT_STATUS_INVALID_NETWORK_RESPONSE;
		}

		if (ln.out.types->count != 1) {
			r->out.error_string = talloc_asprintf(mem_ctx,
								"samr_LookupNames for [%s] returns %d RID TYPEs",
								r->in.account_name, ln.out.types->count);
			talloc_free(tmp_ctx);
			return NT_STATUS_INVALID_NETWORK_RESPONSE;
		}

		/* prepare samr_OpenUser */
		ZERO_STRUCTP(u_handle);
		ou.in.domain_handle = &d_handle;
		ou.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
		ou.in.rid = ln.out.rids->ids[0];
		rid = ou.in.rid;
		ou.out.user_handle = u_handle;
		
		/* 6. do a samr_OpenUser to get a user handle */
		status = dcerpc_samr_OpenUser_r(samr_pipe->binding_handle, tmp_ctx, &ou);
		if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(ou.out.result)) {
			status = ou.out.result;
		}
		if (!NT_STATUS_IS_OK(status)) {
			r->out.error_string = talloc_asprintf(mem_ctx,
							"samr_OpenUser for [%s] failed: %s",
							r->in.account_name,
							nt_errstr(status));
			talloc_free(tmp_ctx);
			return status;
		}

		if (r->in.recreate_account) {
			struct samr_DeleteUser d;
			d.in.user_handle = u_handle;
			d.out.user_handle = u_handle;
			status = dcerpc_samr_DeleteUser_r(samr_pipe->binding_handle, mem_ctx, &d);
			if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(d.out.result)) {
				status = d.out.result;
			}
			if (!NT_STATUS_IS_OK(status)) {
				r->out.error_string = talloc_asprintf(mem_ctx,
								      "samr_DeleteUser (for recreate) of [%s] failed: %s",
								      r->in.account_name,
								      nt_errstr(status));
				talloc_free(tmp_ctx);
				return status;
			}

			/* We want to recreate, so delete and another samr_CreateUser2 */
			
			/* &cu filled in above */
			status = dcerpc_samr_CreateUser2_r(samr_pipe->binding_handle, tmp_ctx, &cu);
			if (NT_STATUS_IS_OK(status) && !NT_STATUS_IS_OK(cu.out.result)) {
				status = cu.out.result;
			}
			if (!NT_STATUS_IS_OK(status)) {
				r->out.error_string = talloc_asprintf(mem_ctx,
								      "samr_CreateUser2 (recreate) for [%s] failed: %s",
								      r->in.account_name, nt_errstr(status));
				talloc_free(tmp_ctx);
				return status;
			}
		}
	} else if (!NT_STATUS_IS_OK(status)) {
Ejemplo n.º 22
0
/*
  handler for completion of a smbcli_request sub-request
*/
static void request_handler(struct smbcli_request *req)
{
	struct composite_context *c = (struct composite_context *)req->async.private_data;
	struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state);
	struct smbcli_session *session = req->session;
	DATA_BLOB session_key = data_blob(NULL, 0);
	DATA_BLOB null_data_blob = data_blob(NULL, 0);
	NTSTATUS session_key_err, nt_status;
	struct smbcli_request *check_req = NULL;
	const char *os = NULL;
	const char *lanman = NULL;

	if (req->sign_caller_checks) {
		req->do_not_free = true;
		check_req = req;
	}

	state->remote_status = smb_raw_sesssetup_recv(req, state, &state->setup);
	c->status = state->remote_status;
	state->req = NULL;

	/*
	 * we only need to check the signature if the
	 * NT_STATUS_OK is returned
	 */
	if (!NT_STATUS_IS_OK(state->remote_status)) {
		talloc_free(check_req);
		check_req = NULL;
	}

	switch (state->setup.old.level) {
	case RAW_SESSSETUP_OLD:
		state->io->out.vuid = state->setup.old.out.vuid;
		/* This doesn't work, as this only happens on old
		 * protocols, where this comparison won't match. */
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we neet to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_old(c, session, 
							      state->io, 
							      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		os = state->setup.old.out.os;
		lanman = state->setup.old.out.lanman;
		break;

	case RAW_SESSSETUP_NT1:
		state->io->out.vuid = state->setup.nt1.out.vuid;
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we neet to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_nt1(c, session, 
							      state->io, 
							      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		os = state->setup.nt1.out.os;
		lanman = state->setup.nt1.out.lanman;
		break;

	case RAW_SESSSETUP_SPNEGO:
		state->io->out.vuid = state->setup.spnego.out.vuid;
		if (NT_STATUS_EQUAL(c->status, NT_STATUS_LOGON_FAILURE)) {
			/* we need to reset the vuid for a new try */
			session->vuid = 0;
			if (cli_credentials_wrong_password(state->io->in.credentials)) {
				nt_status = session_setup_spnego(c, session, 
								      state->io, 
								      &state->req);
				if (NT_STATUS_IS_OK(nt_status)) {
					talloc_free(check_req);
					c->status = nt_status;
					composite_continue_smb(c, state->req, request_handler, c);
					return;
				}
			}
		}
		if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
		    !NT_STATUS_IS_OK(c->status)) {
			break;
		}
		if (NT_STATUS_EQUAL(state->gensec_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {

			/* The status value here, from the earlier pass at GENSEC is
			 * vital to the security of the system.  Even if the other end
			 * accepts, if GENSEC claims 'MORE_PROCESSING_REQUIRED' then
			 * you must keep feeding it blobs, or else the remote
			 * host/attacker might avoid mutal authentication
			 * requirements */
			
			state->gensec_status = gensec_update(session->gensec, state,
							 state->setup.spnego.out.secblob,
							 &state->setup.spnego.in.secblob);
			c->status = state->gensec_status;
			if (!NT_STATUS_EQUAL(c->status, NT_STATUS_MORE_PROCESSING_REQUIRED) && 
			    !NT_STATUS_IS_OK(c->status)) {
				break;
			}
		} else {
			state->setup.spnego.in.secblob = data_blob(NULL, 0);
		}

		if (NT_STATUS_IS_OK(state->remote_status)) {
			if (state->setup.spnego.in.secblob.length) {
				c->status = NT_STATUS_INTERNAL_ERROR;
				break;
			}
			session_key_err = gensec_session_key(session->gensec, &session_key);
			if (NT_STATUS_IS_OK(session_key_err)) {
				set_user_session_key(session, &session_key);
				smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob);
			}
		}

		if (state->setup.spnego.in.secblob.length) {
			/* 
			 * set the session->vuid value only for calling
			 * smb_raw_sesssetup_send()
			 */
			uint16_t vuid = session->vuid;
			session->vuid = state->io->out.vuid;
			state->req = smb_raw_sesssetup_send(session, &state->setup);
			session->vuid = vuid;
			if (state->req) {
				state->req->sign_caller_checks = true;
			}
			composite_continue_smb(c, state->req, request_handler, c);
			return;
		}
		os = state->setup.spnego.out.os;
		lanman = state->setup.spnego.out.lanman;
		break;

	case RAW_SESSSETUP_SMB2:
		c->status = NT_STATUS_INTERNAL_ERROR;
		break;
	}

	if (check_req) {
		check_req->sign_caller_checks = false;
		if (!smbcli_request_check_sign_mac(check_req)) {
			c->status = NT_STATUS_ACCESS_DENIED;
		}
		talloc_free(check_req);
		check_req = NULL;
	}

	/* enforce the local signing required flag */
	if (NT_STATUS_IS_OK(c->status) && !cli_credentials_is_anonymous(state->io->in.credentials)) {
		if (!session->transport->negotiate.sign_info.doing_signing 
		    && session->transport->negotiate.sign_info.mandatory_signing) {
			DEBUG(0, ("SMB signing required, but server does not support it\n"));
			c->status = NT_STATUS_ACCESS_DENIED;
		}
	}

	if (!NT_STATUS_IS_OK(c->status)) {
		composite_error(c, c->status);
		return;
	}

	if (os) {
		session->os = talloc_strdup(session, os);
		if (composite_nomem(session->os, c)) return;
	} else {
		session->os = NULL;
	}
	if (lanman) {
		session->lanman = talloc_strdup(session, lanman);
		if (composite_nomem(session->lanman, c)) return;
	} else {
		session->lanman = NULL;
	}

	composite_done(c);
}
Ejemplo n.º 23
0
static WERROR reg_write_tree(REGF_FILE *regfile, const char *keypath,
			     REGF_NK_REC *parent)
{
	REGF_NK_REC *key;
	struct regval_ctr *values;
	struct regsubkey_ctr *subkeys;
	int i, num_subkeys;
	char *key_tmp = NULL;
	char *keyname, *parentpath;
	char *subkeypath = NULL;
	char *subkeyname;
	struct registry_key_handle registry_key;
	WERROR result = WERR_OK;
	struct security_descriptor *sec_desc = NULL;

	if (!regfile) {
		return WERR_GENERAL_FAILURE;
	}

	if (!keypath) {
		return WERR_OBJECT_PATH_INVALID;
	}

	/* split up the registry key path */

	key_tmp = talloc_strdup(regfile->mem_ctx, keypath);
	if (!key_tmp) {
		return WERR_NOMEM;
	}
	if (!reg_split_key(key_tmp, &parentpath, &keyname)) {
		return WERR_OBJECT_PATH_INVALID;
	}

	if (!keyname) {
		keyname = parentpath;
	}

	/* we need a registry_key_handle object here to enumerate subkeys and values */

	ZERO_STRUCT(registry_key);

	registry_key.name = talloc_strdup(regfile->mem_ctx, keypath);
	if (registry_key.name == NULL) {
		return WERR_NOMEM;
	}

	registry_key.ops = reghook_cache_find(registry_key.name);
	if (registry_key.ops == NULL) {
		return WERR_BADFILE;
	}

	/* lookup the values and subkeys */

	result = regsubkey_ctr_init(regfile->mem_ctx, &subkeys);
	W_ERROR_NOT_OK_RETURN(result);

	result = regval_ctr_init(subkeys, &values);
	W_ERROR_NOT_OK_RETURN(result);

	fetch_reg_keys(&registry_key, subkeys);
	fetch_reg_values(&registry_key, values);

	result = regkey_get_secdesc(regfile->mem_ctx, &registry_key, &sec_desc);
	if (!W_ERROR_IS_OK(result)) {
		goto done;
	}

	/* write out this key */

	key = regfio_write_key(regfile, keyname, values, subkeys, sec_desc,
			       parent);
	if (key == NULL) {
		result = WERR_CAN_NOT_COMPLETE;
		goto done;
	}

	/* write each one of the subkeys out */

	num_subkeys = regsubkey_ctr_numkeys(subkeys);
	for (i=0; i<num_subkeys; i++) {
		subkeyname = regsubkey_ctr_specific_key(subkeys, i);
		subkeypath = talloc_asprintf(regfile->mem_ctx, "%s\\%s",
					     keypath, subkeyname);
		if (subkeypath == NULL) {
			result = WERR_NOMEM;
			goto done;
		}
		result = reg_write_tree(regfile, subkeypath, key);
		if (!W_ERROR_IS_OK(result))
			goto done;
	}

	DEBUG(6, ("reg_write_tree: wrote key [%s]\n", keypath));

done:
	TALLOC_FREE(subkeys);
	TALLOC_FREE(registry_key.name);

	return result;
}
Ejemplo n.º 24
0
errno_t sss_ncache_prepopulate(struct sss_nc_ctx *ncache,
                               struct confdb_ctx *cdb,
                               struct resp_ctx *rctx)
{
    errno_t ret;
    bool filter_set = false;
    char **filter_list = NULL;
    char *name = NULL;
    struct sss_domain_info *dom = NULL;
    struct sss_domain_info *domain_list = rctx->domains;
    char *domainname = NULL;
    char *conf_path = NULL;
    TALLOC_CTX *tmpctx = talloc_new(NULL);
    int i;

    /* Populate domain-specific negative cache entries */
    for (dom = domain_list; dom; dom = get_next_domain(dom, 0)) {
        conf_path = talloc_asprintf(tmpctx, CONFDB_DOMAIN_PATH_TMPL,
                                    dom->name);
        if (!conf_path) {
            ret = ENOMEM;
            goto done;
        }

        talloc_zfree(filter_list);
        ret = confdb_get_string_as_list(cdb, tmpctx, conf_path,
                                        CONFDB_NSS_FILTER_USERS,
                                        &filter_list);
        if (ret == ENOENT) continue;
        if (ret != EOK) goto done;
        filter_set = true;

        for (i = 0; (filter_list && filter_list[i]); i++) {
            ret = sss_parse_name_for_domains(tmpctx, domain_list,
                                             rctx->default_domain,
                                             filter_list[i],
                                             &domainname, &name);
            if (ret == EAGAIN) {
                DEBUG(SSSDBG_MINOR_FAILURE,
                      "cannot add [%s] to negcache because the required or "
                      "default domain are not known yet\n", filter_list[i]);
            } else if (ret != EOK) {
                DEBUG(SSSDBG_CRIT_FAILURE,
                      "Invalid name in filterUsers list: [%s] (%d)\n",
                         filter_list[i], ret);
                continue;
            }

            if (domainname && strcmp(domainname, dom->name)) {
                DEBUG(SSSDBG_CRIT_FAILURE,
                      "Mismatch between domain name (%s) and name "
                          "set in FQN  (%s), skipping user %s\n",
                          dom->name, domainname, name);
                continue;
            }

            ret = sss_ncache_set_user(ncache, true, dom, name);
            if (ret != EOK) {
                DEBUG(SSSDBG_CRIT_FAILURE,
                      "Failed to store permanent user filter for [%s]"
                          " (%d [%s])\n", filter_list[i],
                          ret, strerror(ret));
                continue;
            }
        }
    }

    ret = confdb_get_string_as_list(cdb, tmpctx, CONFDB_NSS_CONF_ENTRY,
                                    CONFDB_NSS_FILTER_USERS, &filter_list);
    if (ret == ENOENT) {
        if (!filter_set) {
            filter_list = talloc_array(tmpctx, char *, 2);
            if (!filter_list) {
                ret = ENOMEM;
                goto done;
            }
            filter_list[0] = talloc_strdup(tmpctx, "root");
            if (!filter_list[0]) {
                ret = ENOMEM;
                goto done;
            }
            filter_list[1] = NULL;
        }
    }
Ejemplo n.º 25
0
static int vfs_gpfs_get_real_filename(struct vfs_handle_struct *handle,
				      const char *path,
				      const char *name,
				      TALLOC_CTX *mem_ctx,
				      char **found_name)
{
	int result;
	char *full_path;
	char real_pathname[PATH_MAX+1];
	int buflen;

	full_path = talloc_asprintf(talloc_tos(), "%s/%s", path, name);
	if (full_path == NULL) {
		errno = ENOMEM;
		return -1;
	}

	buflen = sizeof(real_pathname) - 1;

	result = smbd_gpfs_get_realfilename_path(full_path, real_pathname,
						 &buflen);

	TALLOC_FREE(full_path);

	if ((result == -1) && (errno == ENOSYS)) {
		return SMB_VFS_NEXT_GET_REAL_FILENAME(
			handle, path, name, mem_ctx, found_name);
	}

	if (result == -1) {
		DEBUG(10, ("smbd_gpfs_get_realfilename_path returned %s\n",
			   strerror(errno)));
		return -1;
	}

	/*
	 * GPFS does not necessarily null-terminate the returned path
	 * but instead returns the buffer length in buflen.
	 */

	if (buflen < sizeof(real_pathname)) {
		real_pathname[buflen] = '\0';
	} else {
		real_pathname[sizeof(real_pathname)-1] = '\0';
	}

	DEBUG(10, ("smbd_gpfs_get_realfilename_path: %s/%s -> %s\n",
		   path, name, real_pathname));

	name = strrchr_m(real_pathname, '/');
	if (name == NULL) {
		errno = ENOENT;
		return -1;
	}

	*found_name = talloc_strdup(mem_ctx, name+1);
	if (*found_name == NULL) {
		errno = ENOMEM;
		return -1;
	}

	return 0;
}
Ejemplo n.º 26
0
static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg)
{
    struct mgcp_msg_ptr data_ptrs[6];
    int found, i, line_start;
    const char *trans_id;
    struct mgcp_trunk_config *tcfg;
    struct mgcp_endpoint *endp;
    int error_code = 400;

    found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
    if (found != 0)
        return create_err_response(510, "CRCX", trans_id);

    tcfg = endp->tcfg;

    if (endp->allocated) {
        if (tcfg->force_realloc) {
            LOGP(DMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n",
                 ENDPOINT_NUMBER(endp));
            mgcp_free_endp(endp);
            if (cfg->realloc_cb)
                cfg->realloc_cb(tcfg, ENDPOINT_NUMBER(endp));
        } else {
            LOGP(DMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n",
                 ENDPOINT_NUMBER(endp));
            return create_err_response(400, "CRCX", trans_id);
        }
    }

    /* parse CallID C: and LocalParameters L: */
    MSG_TOKENIZE_START
    switch (msg->l3h[line_start]) {
    case 'L':
        endp->local_options = talloc_strdup(tcfg->endpoints,
                                            (const char *)&msg->l3h[line_start + 3]);
        break;
    case 'C':
        endp->callid = talloc_strdup(tcfg->endpoints,
                                     (const char *)&msg->l3h[line_start + 3]);
        break;
    case 'M':
        if (parse_conn_mode((const char *)&msg->l3h[line_start + 3],
                            &endp->conn_mode) != 0) {
            error_code = 517;
            goto error2;
        }

        endp->orig_mode = endp->conn_mode;
        break;
    default:
        LOGP(DMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
             msg->l3h[line_start], msg->l3h[line_start],
             ENDPOINT_NUMBER(endp));
        break;
    }
    MSG_TOKENIZE_END

    /* initialize */
    endp->net_end.rtp_port = endp->net_end.rtcp_port = endp->bts_end.rtp_port = endp->bts_end.rtcp_port = 0;

    /* set to zero until we get the info */
    memset(&endp->net_end.addr, 0, sizeof(endp->net_end.addr));

    /* bind to the port now */
    if (allocate_ports(endp) != 0)
        goto error2;

    /* assign a local call identifier or fail */
    endp->ci = generate_call_id(cfg);
    if (endp->ci == CI_UNUSED)
        goto error2;

    endp->allocated = 1;
    endp->bts_end.payload_type = tcfg->audio_payload;

    /* policy CB */
    if (cfg->policy_cb) {
        switch (cfg->policy_cb(tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX, trans_id)) {
        case MGCP_POLICY_REJECT:
            LOGP(DMGCP, LOGL_NOTICE, "CRCX rejected by policy on 0x%x\n",
                 ENDPOINT_NUMBER(endp));
            mgcp_free_endp(endp);
            return create_err_response(400, "CRCX", trans_id);
            break;
        case MGCP_POLICY_DEFER:
            /* stop processing */
            create_transcoder(endp);
            return NULL;
            break;
        case MGCP_POLICY_CONT:
            /* just continue */
            break;
        }
    }

    LOGP(DMGCP, LOGL_DEBUG, "Creating endpoint on: 0x%x CI: %u port: %u/%u\n",
         ENDPOINT_NUMBER(endp), endp->ci,
         endp->net_end.local_port, endp->bts_end.local_port);
    if (cfg->change_cb)
        cfg->change_cb(tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX);

    create_transcoder(endp);
    return create_response_with_sdp(endp, "CRCX", trans_id);
error:
    LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d\n",
         osmo_hexdump(msg->l3h, msgb_l3len(msg)),
         ENDPOINT_NUMBER(endp), line_start, i);
    return create_err_response(error_code, "CRCX", trans_id);

error2:
    mgcp_free_endp(endp);
    LOGP(DMGCP, LOGL_NOTICE, "Resource error on 0x%x\n", ENDPOINT_NUMBER(endp));
    return create_err_response(error_code, "CRCX", trans_id);
}
Ejemplo n.º 27
0
static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx,
					   struct netr_DELTA_USER *r,
					   GROUPMAP *groupmap,
					   ACCOUNTMAP *accountmap,
					   FILE *add_fd,
					   const char *sid,
					   const char *suffix,
					   int alloced)
{
	fstring username, logonscript, homedrive, homepath = "", homedir = "";
	fstring hex_nt_passwd, hex_lm_passwd;
	fstring description, profilepath, fullname, sambaSID;
	char *flags, *user_rdn;
	const char *ou;
	const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
	uchar zero_buf[16];
	uint32 rid = 0, group_rid = 0, gidNumber = 0;
	time_t unix_time;
	int i, ret;

	memset(zero_buf, '\0', sizeof(zero_buf));

	/* Get the username */
	fstrcpy(username, r->account_name.string);

	/* Get the rid */
	rid = r->rid;

	/* Map the rid and username for group member info later */
	accountmap->rid = rid;
	accountmap->cn = talloc_strdup(mem_ctx, username);
	NT_STATUS_HAVE_NO_MEMORY(accountmap->cn);

	/* Get the home directory */
	if (r->acct_flags & ACB_NORMAL) {
		fstrcpy(homedir, r->home_directory.string);
		if (!*homedir) {
			snprintf(homedir, sizeof(homedir), "/home/%s", username);
		} else {
			snprintf(homedir, sizeof(homedir), "/nobodyshomedir");
		}
		ou = lp_ldap_user_suffix();
	} else {
		ou = lp_ldap_machine_suffix();
		snprintf(homedir, sizeof(homedir), "/machinehomedir");
	}

        /* Get the logon script */
	fstrcpy(logonscript, r->logon_script.string);

        /* Get the home drive */
	fstrcpy(homedrive, r->home_drive.string);

        /* Get the home path */
	fstrcpy(homepath, r->home_directory.string);

	/* Get the description */
	fstrcpy(description, r->description.string);

	/* Get the display name */
	fstrcpy(fullname, r->full_name.string);

	/* Get the profile path */
	fstrcpy(profilepath, r->profile_path.string);

	/* Get lm and nt password data */
	if (memcmp(r->lmpassword.hash, zero_buf, 16) != 0) {
		pdb_sethexpwd(hex_lm_passwd, r->lmpassword.hash, r->acct_flags);
	} else {
		pdb_sethexpwd(hex_lm_passwd, NULL, 0);
	}
	if (memcmp(r->ntpassword.hash, zero_buf, 16) != 0) {
		pdb_sethexpwd(hex_nt_passwd, r->ntpassword.hash, r->acct_flags);
	} else {
		pdb_sethexpwd(hex_nt_passwd, NULL, 0);
	}
	unix_time = nt_time_to_unix(r->last_password_change);

	/* Increment the uid for the new user */
	ldif_uid++;

	/* Set up group id and sambaSID for the user */
	group_rid = r->primary_gid;
	for (i=0; i<alloced; i++) {
		if (groupmap[i].rid == group_rid) break;
	}
	if (i == alloced){
		DEBUG(1, ("Could not find rid %d in groupmap array\n",
			  group_rid));
		return NT_STATUS_UNSUCCESSFUL;
	}
	gidNumber = groupmap[i].gidNumber;
	ret = snprintf(sambaSID, sizeof(sambaSID), "%s", groupmap[i].sambaSID);
	if (ret < 0 || ret == sizeof(sambaSID)) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Set up sambaAcctFlags */
	flags = pdb_encode_acct_ctrl(r->acct_flags,
				     NEW_PW_FORMAT_SPACE_PADDED_LEN);

	/* Add the user to the temporary add ldif file */
	/* this isn't quite right...we can't assume there's just OU=. jmcd */
	user_rdn = sstring_sub(ou, '=', ',');
	fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix);
	fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn,
		     suffix);
	SAFE_FREE(user_rdn);
	fprintf(add_fd, "ObjectClass: top\n");
	fprintf(add_fd, "objectClass: inetOrgPerson\n");
	fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT);
	fprintf(add_fd, "objectClass: shadowAccount\n");
	fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT);
	fprintf_attr(add_fd, "cn", "%s", username);
	fprintf_attr(add_fd, "sn", "%s", username);
	fprintf_attr(add_fd, "uid", "%s", username);
	fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
	fprintf(add_fd, "gidNumber: %d\n", gidNumber);
	fprintf_attr(add_fd, "homeDirectory", "%s", homedir);
	if (*homepath)
		fprintf_attr(add_fd, "sambaHomePath", "%s", homepath);
        if (*homedrive)
                fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive);
        if (*logonscript)
                fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript);
	fprintf(add_fd, "loginShell: %s\n",
		((r->acct_flags & ACB_NORMAL) ?
		 "/bin/bash" : "/bin/false"));
	fprintf(add_fd, "gecos: System User\n");
	if (*description)
		fprintf_attr(add_fd, "description", "%s", description);
	fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
	fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
	if(*fullname)
		fprintf_attr(add_fd, "displayName", "%s", fullname);
	if(*profilepath)
		fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath);
	if (strcmp(nopasswd, hex_lm_passwd) != 0)
		fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
	if (strcmp(nopasswd, hex_nt_passwd) != 0)
		fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd);
	fprintf(add_fd, "sambaPwdLastSet: %d\n", (int)unix_time);
	fprintf(add_fd, "sambaAcctFlags: %s\n", flags);
	fprintf(add_fd, "\n");
	fflush(add_fd);

	/* Return */
	return NT_STATUS_OK;
}
Ejemplo n.º 28
0
static struct winbindd_domain *add_trusted_domain(const char *domain_name, const char *alt_name,
						  struct winbindd_methods *methods,
						  const struct dom_sid *sid)
{
	struct winbindd_domain *domain;
	const char *alternative_name = NULL;
	const char **ignored_domains, **dom;
	int role = lp_server_role();

	ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
	for (dom=ignored_domains; dom && *dom; dom++) {
		if (gen_fnmatch(*dom, domain_name) == 0) {
			DEBUG(2,("Ignoring domain '%s'\n", domain_name));
			return NULL;
		}
	}

	/* use alt_name if available to allow DNS lookups */

	if (alt_name && *alt_name) {
		alternative_name = alt_name;
	}

	/* We can't call domain_list() as this function is called from
	   init_domain_list() and we'll get stuck in a loop. */
	for (domain = _domain_list; domain; domain = domain->next) {
		if (strequal(domain_name, domain->name) ||
		    strequal(domain_name, domain->alt_name))
		{
			break;
		}

		if (alternative_name && *alternative_name)
		{
			if (strequal(alternative_name, domain->name) ||
			    strequal(alternative_name, domain->alt_name))
			{
				break;
			}
		}

		if (sid)
		{
			if (is_null_sid(sid)) {
				continue;
			}

			if (dom_sid_equal(sid, &domain->sid)) {
				break;
			}
		}
	}

	if (domain != NULL) {
		/*
		 * We found a match on domain->name or
		 * domain->alt_name. Possibly update the SID
		 * if the stored SID was the NULL SID
		 * and return the matching entry.
		 */
		if ((sid != NULL)
		    && dom_sid_equal(&domain->sid, &global_sid_NULL)) {
			sid_copy( &domain->sid, sid );
		}
		return domain;
	}

	/* Create new domain entry */
	domain = talloc_zero(NULL, struct winbindd_domain);
	if (domain == NULL) {
		return NULL;
	}

	domain->children = talloc_zero_array(domain,
					     struct winbindd_child,
					     lp_winbind_max_domain_connections());
	if (domain->children == NULL) {
		TALLOC_FREE(domain);
		return NULL;
	}

	domain->name = talloc_strdup(domain, domain_name);
	if (domain->name == NULL) {
		TALLOC_FREE(domain);
		return NULL;
	}

	if (alternative_name) {
		domain->alt_name = talloc_strdup(domain, alternative_name);
		if (domain->alt_name == NULL) {
			TALLOC_FREE(domain);
			return NULL;
		}
	}

	domain->methods = methods;
	domain->backend = NULL;
	domain->internal = is_internal_domain(sid);
	domain->sequence_number = DOM_SEQUENCE_NONE;
	domain->last_seq_check = 0;
	domain->initialized = False;
	domain->online = is_internal_domain(sid);
	domain->check_online_timeout = 0;
	domain->dc_probe_pid = (pid_t)-1;
	if (sid) {
		sid_copy(&domain->sid, sid);
	}

	/* Is this our primary domain ? */
	if (strequal(domain_name, get_global_sam_name()) &&
			(role != ROLE_DOMAIN_MEMBER)) {
		domain->primary = true;
	} else if (strequal(domain_name, lp_workgroup()) &&
			(role == ROLE_DOMAIN_MEMBER)) {
		domain->primary = true;
	}

	if (domain->primary) {
		if (role == ROLE_ACTIVE_DIRECTORY_DC) {
			domain->active_directory = true;
		}
		if (lp_security() == SEC_ADS) {
			domain->active_directory = true;
		}
	}

	/* Link to domain list */
	DLIST_ADD_END(_domain_list, domain);

	wcache_tdc_add_domain( domain );

	setup_domain_child(domain);

	DEBUG(2,("Added domain %s %s %s\n",
		 domain->name, domain->alt_name,
		 &domain->sid?sid_string_dbg(&domain->sid):""));

	return domain;
}
Ejemplo n.º 29
0
static int local_db_get_simple(TALLOC_CTX *mem_ctx,
                               struct local_context *lctx,
                               const char *req_path,
                               char **secret)
{
    TALLOC_CTX *tmp_ctx;
    static const char *attrs[] = { "secret", "enctype", NULL };
    struct ldb_result *res;
    struct ldb_dn *dn;
    const char *attr_secret;
    const char *attr_enctype;
    int ret;

    DEBUG(SSSDBG_TRACE_FUNC, "Retrieving a secret from [%s]\n", req_path);

    tmp_ctx = talloc_new(mem_ctx);
    if (!tmp_ctx) return ENOMEM;

    ret = local_db_dn(tmp_ctx, lctx->ldb, req_path, &dn);
    if (ret != EOK) {
        DEBUG(SSSDBG_OP_FAILURE,
              "local_db_dn failed [%d]: %s\n", ret, sss_strerror(ret));
        goto done;
    }

    DEBUG(SSSDBG_TRACE_INTERNAL,
          "Searching for [%s] at [%s] with scope=base\n",
          LOCAL_SIMPLE_FILTER, ldb_dn_get_linearized(dn));

    ret = ldb_search(lctx->ldb, tmp_ctx, &res, dn, LDB_SCOPE_BASE,
                     attrs, "%s", LOCAL_SIMPLE_FILTER);
    if (ret != EOK) {
        DEBUG(SSSDBG_TRACE_LIBS,
              "ldb_search returned [%d]: %s\n", ret, ldb_strerror(ret));
        ret = ENOENT;
        goto done;
    }

    switch (res->count) {
    case 0:
        DEBUG(SSSDBG_TRACE_LIBS, "No secret found\n");
        ret = ENOENT;
        goto done;
    case 1:
        break;
    default:
        DEBUG(SSSDBG_OP_FAILURE,
              "Too many secrets returned with BASE search\n");
        ret = E2BIG;
        goto done;
    }

    attr_secret = ldb_msg_find_attr_as_string(res->msgs[0], "secret", NULL);
    if (!attr_secret) {
        DEBUG(SSSDBG_CRIT_FAILURE, "The 'secret' attribute is missing\n");
        ret = ENOENT;
        goto done;
    }

    attr_enctype = ldb_msg_find_attr_as_string(res->msgs[0], "enctype", NULL);

    if (attr_enctype) {
        ret = local_decrypt(lctx, mem_ctx, attr_secret, attr_enctype, secret);
        if (ret) goto done;
    } else {
        *secret = talloc_strdup(mem_ctx, attr_secret);
    }
    ret = EOK;

done:
    talloc_free(tmp_ctx);
    return ret;
}
Ejemplo n.º 30
0
int pairparsevalue(VALUE_PAIR *vp, char const *value)
{
	char		*p;
	char const	*cp, *cs;
	int		x;
	uint64_t	y;
	size_t		length;
	DICT_VALUE	*dval;

	if (!value) return false;
	VERIFY(vp);

	switch(vp->da->type) {
	case PW_TYPE_STRING:
		/*
		 *	Do escaping here
		 */
		p = talloc_strdup(vp, value);
		vp->vp_strvalue = p;
		cp = value;
		length = 0;

		while (*cp) {
			char c = *cp++;

			if (c == '\\') {
				switch (*cp) {
				case 'r':
					c = '\r';
					cp++;
					break;
				case 'n':
					c = '\n';
					cp++;
					break;
				case 't':
					c = '\t';
					cp++;
					break;
				case '"':
					c = '"';
					cp++;
					break;
				case '\'':
					c = '\'';
					cp++;
					break;
				case '\\':
					c = '\\';
					cp++;
					break;
				case '`':
					c = '`';
					cp++;
					break;
				case '\0':
					c = '\\'; /* no cp++ */
					break;
				default:
					if ((cp[0] >= '0') &&
					    (cp[0] <= '9') &&
					    (cp[1] >= '0') &&
					    (cp[1] <= '9') &&
					    (cp[2] >= '0') &&
					    (cp[2] <= '9') &&
					    (sscanf(cp, "%3o", &x) == 1)) {
						c = x;
						cp += 3;
					} /* else just do '\\' */
				}
			}
			*p++ = c;
			length++;
		}
		*p = '\0';
		vp->length = length;
		break;

	case PW_TYPE_IPADDR:
		/*
		 *	It's a comparison, not a real IP.
		 */
		if ((vp->op == T_OP_REG_EQ) ||
		    (vp->op == T_OP_REG_NE)) {
			break;
		}

		/*
		 *	FIXME: complain if hostname
		 *	cannot be resolved, or resolve later!
		 */
		p = NULL;
		cs = value;

		{
			fr_ipaddr_t ipaddr;

			if (ip_hton(cs, AF_INET, &ipaddr) < 0) {
				fr_strerror_printf("Failed to find IP address for %s", cs);
				return false;
			}

			vp->vp_ipaddr = ipaddr.ipaddr.ip4addr.s_addr;
		}
		vp->length = 4;
		break;

	case PW_TYPE_BYTE:
		vp->length = 1;

		/*
		 *	Note that ALL integers are unsigned!
		 */
		vp->vp_integer = getint(value, &p);
		if (!*p) {
			if (vp->vp_integer > 255) {
				fr_strerror_printf("Byte value \"%s\" is larger than 255", value);
				return false;
			}
			break;
		}
		if (check_for_whitespace(p)) break;
		goto check_for_value;

	case PW_TYPE_SHORT:
		/*
		 *	Note that ALL integers are unsigned!
		 */
		vp->vp_integer = getint(value, &p);
		vp->length = 2;
		if (!*p) {
			if (vp->vp_integer > 65535) {
				fr_strerror_printf("Byte value \"%s\" is larger than 65535", value);
				return false;
			}
			break;
		}
		if (check_for_whitespace(p)) break;
		goto check_for_value;

	case PW_TYPE_INTEGER:
		/*
		 *	Note that ALL integers are unsigned!
		 */
		vp->vp_integer = getint(value, &p);
		vp->length = 4;
		if (!*p) break;
		if (check_for_whitespace(p)) break;

	check_for_value:
		/*
		 *	Look for the named value for the given
		 *	attribute.
		 */
		if ((dval = dict_valbyname(vp->da->attr, vp->da->vendor, value)) == NULL) {
			fr_strerror_printf("Unknown value %s for attribute %s",
				   value, vp->da->name);
			return false;
		}
		vp->vp_integer = dval->value;
		break;

	case PW_TYPE_INTEGER64:
		/*
		 *	Note that ALL integers are unsigned!
		 */
		if (sscanf(vp->vp_strvalue, "%" PRIu64, &y) != 1) {
			fr_strerror_printf("Invalid value %s for attribute %s",
					   value, vp->da->name);
			return false;
		}
		vp->vp_integer64 = y;
		vp->length = 8;
		length = strspn(vp->vp_strvalue, "0123456789");
		if (check_for_whitespace(vp->vp_strvalue + length)) break;
		break;

	case PW_TYPE_DATE:
		{
			/*
			 *	time_t may be 64 bits, whule vp_date
			 *	MUST be 32-bits.  We need an
			 *	intermediary variable to handle
			 *	the conversions.
			 */
			time_t date;

			if (gettime(value, &date) < 0) {
				fr_strerror_printf("failed to parse time string "
					   "\"%s\"", value);
				return false;
			}

			vp->vp_date = date;
		}
		vp->length = 4;
		break;

	case PW_TYPE_ABINARY:
#ifdef WITH_ASCEND_BINARY
		if (strncasecmp(value, "0x", 2) == 0) {
			goto do_octets;
		}

		if (ascend_parse_filter(vp) < 0 ) {
			char buffer[256];

			snprintf(buffer, sizeof(buffer), "failed to parse Ascend binary attribute: %s", fr_strerror());
			fr_strerror_printf("%s", buffer);
			return false;
		}
		break;

		/*
		 *	If Ascend binary is NOT defined,
		 *	then fall through to raw octets, so that
		 *	the user can at least make them by hand...
		 */
#endif
	/* raw octets: 0x01020304... */
	case PW_TYPE_VSA:
		if (strcmp(value, "ANY") == 0) {
			vp->length = 0;
			break;
		} /* else it's hex */

	case PW_TYPE_OCTETS:
		if (strncasecmp(value, "0x", 2) == 0) {
			size_t size;
			uint8_t *us;

#ifdef WITH_ASCEND_BINARY
		do_octets:
#endif
			cp = value + 2;
			size = strlen(cp);
			vp->length = size >> 1;
			us = talloc_array(vp, uint8_t, vp->length);

			/*
			 *	Invalid.
			 */
			if ((size  & 0x01) != 0) {
				fr_strerror_printf("Hex string is not an even length string.");
				return false;
			}

			if (fr_hex2bin(cp, us,
				       vp->length) != vp->length) {
				fr_strerror_printf("Invalid hex data");
				return false;
			}
			vp->vp_octets = us;
		} else {