示例#1
0
/**
 * generic acl checking for different methods (basic set of methods supported)
 * returns null if no err
 */
static dav_error *check_methods(request_rec *r, const dav_resource *resource,
                                davacl_dir_cfg *conf)
{
    const dav_hooks_repository *repos = REPOS(conf);

    if (repos == NULL || resource == NULL)
	return dav_acl_privilege_error(r, "unknown", NULL);

    switch (r->method_number) {
    default:
	if (r->method_number == iM_ACL) {
	    return check_acl(r, resource, conf, repos);
	}
	else if (r->method_number == iM_HEAD) {
	    return check_get(r, resource, conf, repos);
	}
	else {
	    TRACE(r, "Unknown methdod:%d", r->method_number);
	    return NULL;
	}
	break;

    case M_PUT:
	return check_put(r, resource, conf, repos);

    case M_PROPPATCH:
	return check_proppatch(r, resource, conf, repos);

    case M_MKCOL:
	return check_mkcol(r, resource, conf, repos);

    case M_PROPFIND:
	/* done with individual properties within dav_get_props() and
	 * dav_get_allprops */
	return NULL;

    case M_DELETE:
	return check_delete(r, resource, conf, repos);

    case M_OPTIONS:
    case M_GET:
	return check_get(r, resource, conf, repos);

    case M_COPY:
	return check_copy(r, resource, conf, repos);

    case M_MOVE:
	return check_move(r, resource, conf, repos);

    case M_LOCK:
	return check_lock(r, resource, conf, repos);

    case M_UNLOCK:
	return check_unlock(r, resource, conf, repos);
    }
}
示例#2
0
文件: acl.c 项目: Tayyib/uludag
int
acl_is_capable(int cmd, int node, struct Creds *cred)
{
	// root always capable
	if (cred->uid == 0)
		return 1;

	if (cmd == CMD_CALL) {
		if (check_acl(node, cred) == 1)
			return 1;
	}

	return 0;
}
示例#3
0
static 
attribute_not_cached (Entry ptr, DN dn, OID at, DN target, int level, int dfltacl)
{
	struct acl_attr * aa;
	struct oid_seq * oidptr;

	/* see if more than cached data is required */
	if (ptr->e_acl->ac_attributes == NULLACL_ATTR)
		return (dfltacl);

	for ( aa = ptr->e_acl->ac_attributes; aa!=NULLACL_ATTR; aa=aa->aa_next)
		for ( oidptr=aa->aa_types; oidptr != NULLOIDSEQ; oidptr=oidptr->oid_next)
			if (oid_cmp (oidptr->oid_oid,at) == 0) {
				/* The attribute is in the attribute ACL list */
				/* Would a referral help the DUA ? */
				if (check_acl (NULLDN,level,aa->aa_acl,target) == NOTOK)
					if (check_acl (dn,level,aa->aa_acl,target) == OK)
						return TRUE;
				return FALSE;
			}
	return (dfltacl);

}
示例#4
0
static 
cant_use_cache (Entry ptr, DN dn, EntryInfoSelection eis, DN target)
{
	Attr_Sequence as;
	char dfltacl = FALSE;

	if (dn == NULLDN)
		return FALSE;

	if ((ptr->e_data == E_DATA_MASTER) || (ptr->e_data == E_TYPE_SLAVE))
		return FALSE;

	/* see if more than cached data is required */

	if (eis.eis_allattributes) {
		struct acl_attr * aa;
		struct oid_seq * oidptr;
		/* look for attr acl */
		/* see if any attributes use can see */

		if (check_acl (NULLDN,ACL_READ,ptr->e_acl->ac_default,target) == NOTOK)
			if (check_acl (dn,ACL_READ,ptr->e_acl->ac_default,target) == OK)
				return TRUE;

		if (ptr->e_acl->ac_attributes == NULLACL_ATTR)
			return FALSE;

		for ( aa = ptr->e_acl->ac_attributes; aa!=NULLACL_ATTR; aa=aa->aa_next)
			for ( oidptr=aa->aa_types; oidptr != NULLOIDSEQ; oidptr=oidptr->oid_next)
				/* The attribute is in the attribute ACL list */
				/* Would a referral help the DUA ? */
				if (check_acl (NULLDN,ACL_READ,aa->aa_acl,target) == NOTOK)
					if (check_acl (dn,ACL_READ,aa->aa_acl,target) == OK)
						return TRUE;

	} else {
		/* for each attribute in eis.eis_select, see is user
		   entitled to it. */

		if (check_acl (NULLDN,ACL_READ,ptr->e_acl->ac_default,target) == NOTOK)
			if (check_acl (dn,ACL_READ,ptr->e_acl->ac_default,target) == OK)
				dfltacl = TRUE;

		for(as=eis.eis_select; as != NULLATTR; as=as->attr_link) {
			if (entry_find_type (ptr, as->attr_type) == NULLATTR)
				if (attribute_not_cached (ptr,dn,grab_oid(as->attr_type),target,ACL_READ,dfltacl))
					return TRUE;

		}
	}
	return FALSE;
}
示例#5
0
static void
add_slave (krb5_context context, krb5_keytab keytab, slave **root, int fd)
{
    krb5_principal server;
    krb5_error_code ret;
    slave *s;
    socklen_t addr_len;
    krb5_ticket *ticket = NULL;
    char hostname[128];

    s = malloc(sizeof(*s));
    if (s == NULL) {
	krb5_warnx (context, "add_slave: no memory");
	return;
    }
    s->name = NULL;
    s->ac = NULL;

    addr_len = sizeof(s->addr);
    s->fd = accept (fd, (struct sockaddr *)&s->addr, &addr_len);
    if (s->fd < 0) {
	krb5_warn (context, errno, "accept");
	goto error;
    }
    gethostname(hostname, sizeof(hostname));
    ret = krb5_sname_to_principal (context, hostname, IPROP_NAME,
				   KRB5_NT_SRV_HST, &server);
    if (ret) {
	krb5_warn (context, ret, "krb5_sname_to_principal");
	goto error;
    }

    ret = krb5_recvauth (context, &s->ac, &s->fd,
			 IPROP_VERSION, server, 0, keytab, &ticket);
    krb5_free_principal (context, server);
    if (ret) {
	krb5_warn (context, ret, "krb5_recvauth");
	goto error;
    }
    ret = krb5_unparse_name (context, ticket->client, &s->name);
    if (ret) {
	krb5_warn (context, ret, "krb5_unparse_name");
	goto error;
    }
    if (check_acl (context, s->name)) {
	krb5_warnx (context, "%s not in acl", s->name);
	goto error;
    }
    krb5_free_ticket (context, ticket);
    ticket = NULL;

    {
	slave *l = *root;

	while (l) {
	    if (strcmp(l->name, s->name) == 0)
		break;
	    l = l->next;
	}
	if (l) {
	    if (l->flags & SLAVE_F_DEAD) {
		remove_slave(context, l, root);
	    } else {
		krb5_warnx (context, "second connection from %s", s->name);
		goto error;
	    }
	}
    }

    krb5_warnx (context, "connection from %s", s->name);

    s->version = 0;
    s->flags = 0;
    slave_seen(s);
    s->next = *root;
    *root = s;
    return;
error:
    remove_slave(context, s, root);
}
示例#6
0
文件: reqs.c 项目: OPSF/uClinux
/*
 * This is the main drive for each connection. As you can tell, for the
 * first few steps we are using a blocking socket. If you remember the
 * older tinyproxy code, this use to be a very confusing state machine.
 * Well, no more! :) The sockets are only switched into nonblocking mode
 * when we start the relay portion. This makes most of the original
 * tinyproxy code, which was confusing, redundant. Hail progress.
 * 	- rjkaes
 */
void
handle_connection(int fd)
{
	struct conn_s *connptr;
	struct request_s *request = NULL;
	hashmap_t hashofheaders = NULL;

	char peer_ipaddr[PEER_IP_LENGTH];
	char peer_string[PEER_STRING_LENGTH];

	getpeer_information(fd, peer_ipaddr, peer_string);

	log_message(LOG_CONN, "Connect (file descriptor %d): %s [%s]",
		    fd, peer_string, peer_ipaddr);

	connptr = initialize_conn(fd, peer_ipaddr, peer_string);
	if (!connptr) {
		close(fd);
		return;
	}

	if (check_acl(fd, peer_ipaddr, peer_string) <= 0) {
		update_stats(STAT_DENIED);
		indicate_http_error(connptr, 403, "Access denied",
				    "detail", "The administrator of this proxy has not configured it to service requests from your host.",
				    NULL);
		send_http_error_message(connptr);
		destroy_conn(connptr);
		return;
	}

	if (read_request_line(connptr) < 0) {
		update_stats(STAT_BADCONN);
		indicate_http_error(connptr, 408, "Timeout",
				    "detail", "Server timeout waiting for the HTTP request from the client.",
				    NULL);
		send_http_error_message(connptr);
		destroy_conn(connptr);
		return;
	}

	/*
	 * The "hashofheaders" store the client's headers.
	 */
	if (!(hashofheaders = hashmap_create(HEADER_BUCKETS))) {
		update_stats(STAT_BADCONN);
		indicate_http_error(connptr, 503, "Internal error",
				    "detail", "An internal server error occurred while processing your request.  Please contact the administrator.",
				    NULL);
		send_http_error_message(connptr);
		destroy_conn(connptr);
		return;
	}

	/*
	 * Get all the headers from the client in a big hash.
	 */
	if (get_all_headers(connptr->client_fd, hashofheaders) < 0) {
		log_message(LOG_WARNING, "Could not retrieve all the headers from the client");
		hashmap_delete(hashofheaders);
		update_stats(STAT_BADCONN);
		destroy_conn(connptr);
		return;
	}

	request = process_request(connptr, hashofheaders);
	if (!request) {
		if (!connptr->error_variables && !connptr->show_stats) {
			update_stats(STAT_BADCONN);
			destroy_conn(connptr);
			hashmap_delete(hashofheaders);
			return;
		}
		goto send_error;
	}

	connptr->upstream_proxy = UPSTREAM_HOST(request->host);
	if (connptr->upstream_proxy != NULL) {
		if (connect_to_upstream(connptr, request) < 0) {
			goto send_error;
		}
	} else {
		connptr->server_fd = opensock(request->host, request->port);
		if (connptr->server_fd < 0) {
			indicate_http_error(connptr, 500, "Unable to connect",
					    "detail", PACKAGE " was unable to connect to the remote web server.",
					    "error", strerror(errno),
					    NULL);
			goto send_error;
		}

		log_message(LOG_CONN,
			    "Established connection to host \"%s\" using file descriptor %d.",
			    request->host, connptr->server_fd);

		if (!connptr->connect_method)
			establish_http_connection(connptr, request);
	}

      send_error:
	free_request_struct(request);

	if (process_client_headers(connptr, hashofheaders) < 0) {
		update_stats(STAT_BADCONN);
		if (!connptr->error_variables) {
			hashmap_delete(hashofheaders);
			destroy_conn(connptr);
			return;
		}
	}
	hashmap_delete(hashofheaders);

	if (connptr->error_variables) {
		send_http_error_message(connptr);
		destroy_conn(connptr);
		return;
	} else if (connptr->show_stats) {
		showstats(connptr);
		destroy_conn(connptr);
		return;
	}

	if (!connptr->connect_method || (connptr->upstream_proxy != NULL)) {
		if (process_server_headers(connptr) < 0) {
			if (connptr->error_variables)
				send_http_error_message(connptr);

			update_stats(STAT_BADCONN);
			destroy_conn(connptr);
			return;
		}
	} else {
		if (send_ssl_response(connptr) < 0) {
			log_message(LOG_ERR,
				    "handle_connection: Could not send SSL greeting to client.");
			update_stats(STAT_BADCONN);
			destroy_conn(connptr);
			return;
		}
	}

	relay_connection(connptr);

	log_message(LOG_INFO, "Closed connection between local client (fd:%d) and remote client (fd:%d)",
		    connptr->client_fd, connptr->server_fd);

	/*
	 * All done... close everything and go home... :)
	 */
	destroy_conn(connptr);
	return;
}
示例#7
0
int 
find_entry (DN object, common_args *ca, DN acl_who, struct dn_seq *dn_stack, int master, Entry *ent_p, struct DSError *err, struct di_block **di_p, int optype)
{
	int deref = FALSE;
	extern time_t cache_timeout;
	DN dn_found;
	int res;

	DLOG (log_dsap,LLOG_TRACE,("find_entry"));
	err->dse_type = DSE_NOERROR;

	if ((ca->ca_servicecontrol.svc_options & SVC_OPT_DONTDEREFERENCEALIAS) == 0)
		deref = TRUE;

	if ((ca->ca_servicecontrol.svc_options & SVC_OPT_DONTUSECOPY) != 0)
		master = TRUE;

	switch(really_find_entry(object,deref,dn_stack,master,ent_p,err,di_p)) {
	case DS_OK:
		DLOG(log_dsap, LLOG_DEBUG, ("find_entry - rfe: OK"));
		/* Have set up ent_p continue processing */
		break;

	case DS_CONTINUE:
		DLOG(log_dsap, LLOG_DEBUG, ("find_entry - rfe: CONT"));
#ifdef DEBUG
		di_list_log((*di_p));
#endif
		/* Have set up di_blocks of DSAs to be questioned */
		return(DS_CONTINUE);

	case DS_X500_ERROR:
		DLOG(log_dsap, LLOG_DEBUG, ("find_entry - rfe: X500_ERROR"));
		/* Have set up an error */
		return(DS_X500_ERROR);

	default:
		/* Scream */
		LLOG(log_dsap, LLOG_EXCEPTIONS, ("really_find_entry failed in find_entry 1"));
		return(DS_ERROR_LOCAL);
	}

	dn_found = get_copy_dn (*ent_p);

	/* if the returned entry is a CONSTRUCTOR, return a referral */
	if ((*ent_p)->e_data == E_TYPE_CONSTRUCTOR) {
		DLOG(log_dsap, LLOG_DEBUG, ("find_entry - constructor"));
		res = constructor_dsa_info(dn_found,dn_stack,FALSE,(*ent_p),err,di_p);
		dn_free (dn_found);
		return (res);
	}

	/* if the returned entry is a COPY, - check service controls */
	if (((*ent_p)->e_data != E_DATA_MASTER) && (master)) {

		/* DSAs are special for read/modify */
		if ((optype == OP_READ) ||
				(optype == OP_MODIFYRDN) ||
				(optype == OP_MODIFYENTRY)) {
			if ((quipu_ctx_supported (*ent_p) > 2) && (quipu_version_7 (*ent_p))) {
				if (dn_cmp (dn_found, mydsadn) == 0)
					goto out;
mk_ref:
				;
				(*di_p) = di_alloc();
				(*di_p)->di_type = DI_TASK;
				(*di_p)->di_dn = dn_found;
				(*di_p)->di_target = dn_cpy(dn_found);
				(*di_p)->di_reftype = RT_UNDEFINED;
				(*di_p)->di_rdn_resolved = CR_RDNRESOLVED_NOTDEFINED;
				(*di_p)->di_aliasedRDNs = CR_NOALIASEDRDNS;
				(*di_p)->di_entry = *ent_p;
				(*ent_p)->e_refcount++;
				(*di_p)->di_state = DI_COMPLETE;
				return DS_CONTINUE;
			}
		}

		DLOG(log_dsap, LLOG_DEBUG, ("find_entry - slave master needed"));
		res = constructor_dsa_info(dn_found,dn_stack,TRUE,(*ent_p),err,di_p);
		dn_free (dn_found);
		return (res);

	} else if ( ((optype == OP_MODIFYRDN) || (optype == OP_MODIFYENTRY)) &&
				(quipu_ctx_supported (*ent_p) > 2) &&
				quipu_version_7 (*ent_p) &&
				(dn_cmp (dn_found, mydsadn) != 0))
		goto mk_ref;

#ifdef WRONG_BEHAVIOUR

	/* if this is right, we need to make sure that dsa_info */
	/* pick ups the correct external reference */

	if ((*ent_p)->e_external &&
			((*ent_p)->e_reftype != RT_NONSPECIFICSUBORDINATE)) {
		res = constructor_dsa_info(dn_found,dn_stack,TRUE,(*ent_p),err,di_p);
		dn_free (dn_found);
		return (res);
	}
#endif

	if (((*ent_p)->e_data == E_TYPE_CACHE_FROM_MASTER) &&
			(timenow - (*ent_p)->e_age > cache_timeout)) {
		DLOG(log_dsap, LLOG_DEBUG, ("find_entry - cache timed out"));
		res = constructor_dsa_info(dn_found,dn_stack,TRUE,(*ent_p),err,di_p);
		delete_cache (dn_found);
		dn_free (dn_found);
		return (res);
	}

out:
	;
	dn_free (dn_found);

	if ((*ent_p)->e_parent == NULLENTRY) {
		DLOG(log_dsap, LLOG_DEBUG, ("find_entry: (*ent_p)->e_parent is NULLENTRY"));
		return (DS_OK);     /* no acl for root entry */
	}

	if (check_acl (acl_who,ACL_DETECT, (*ent_p)->e_parent->e_acl->ac_child, object) == NOTOK) {
		err->dse_type = DSE_SECURITYERROR;
		err->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
		return (DS_X500_ERROR);
	}

	if (check_acl (acl_who,ACL_DETECT, (*ent_p)->e_acl->ac_entry, object) == NOTOK) {
		err->dse_type = DSE_SECURITYERROR;
		err->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
		return (DS_X500_ERROR);
	}

	return (DS_OK);
}
示例#8
0
int 
find_child_entry (DN object, common_args *ca, DN acl_who, struct dn_seq *dn_stack, int master, Entry *ent_p, struct DSError *err, struct di_block **di_p)
{
	/* this is very similar to find_entry(), except a top level */
	/* constructor is allowed */
	int deref = FALSE;
	int res;
	DN dn_found;
	Entry	akid;

	DLOG (log_dsap,LLOG_DEBUG,("find_child_entry"));
	err->dse_type = DSE_NOERROR;

	if ((ca->ca_servicecontrol.svc_options & SVC_OPT_DONTDEREFERENCEALIAS) == 0)
		deref = TRUE;

	if ((ca->ca_servicecontrol.svc_options & SVC_OPT_DONTUSECOPY) != 0)
		master = TRUE;

	switch(really_find_entry(object,deref,dn_stack,master,ent_p,err,di_p)) {
	case DS_OK:
		DLOG(log_dsap, LLOG_DEBUG, ("find_child_entry - rfe: OK"));
		/* Have set up ent_p continue processing */
		break;

	case DS_CONTINUE:
		DLOG(log_dsap, LLOG_DEBUG, ("find_child_entry - rfe: CONTINUE"));
#ifdef DEBUG
		di_list_log((*di_p));
#endif
		/* Have set up di_blocks of DSAs to be questioned */
		return(DS_CONTINUE);

	case DS_X500_ERROR:
		/* Have set up an error */
		DLOG(log_dsap, LLOG_DEBUG, ("find_child_entry - rfe: X500_ERROR"));
		return(DS_X500_ERROR);

	default:
		/* Scream */
		LLOG(log_dsap, LLOG_EXCEPTIONS, ("really_find_entry failed in find_entry 1"));
		return(DS_ERROR_LOCAL);
	}

	/* check to see if children OK */
	if ((*ent_p)->e_children != NULLAVL && (*ent_p)->e_allchildrenpresent
			!= FALSE) {
		DLOG(log_dsap, LLOG_DEBUG, ("find_child_entry - children OK"));
		akid = (Entry) avl_getone((*ent_p)->e_children);
		switch (akid->e_data) {
		case E_DATA_MASTER:
			DLOG(log_dsap, LLOG_DEBUG, ("find_child_entry - children masters"));
			break;
		case E_TYPE_SLAVE:
			/* see if we can use a copy ... */
			DLOG(log_dsap, LLOG_DEBUG, ("find_child_entry - children slaves"));
			if (master) {
				dn_found = get_copy_dn (*ent_p);
				res = constructor_dsa_info_aux(dn_found,dn_stack,master,(*ent_p),err,di_p);
				dn_free (dn_found);
				return (res);
			}
			break;
		default:
			DLOG(log_dsap, LLOG_DEBUG, ("find_child_entry - default"));
			dn_found = get_copy_dn (*ent_p);
			res = constructor_dsa_info_aux(dn_found,dn_stack,master,(*ent_p),err,di_p);
			dn_free (dn_found);
			return (res);
		}
	} else if ( (! isleaf(*ent_p)) || (*ent_p)->e_external) {
		DLOG(log_dsap, LLOG_DEBUG, ("find_child_entry - children NOTOK"));
		dn_found = get_copy_dn (*ent_p);
		res = constructor_dsa_info_aux(dn_found,dn_stack,master,(*ent_p),err,di_p);
		dn_free (dn_found);
		return (res);
	}

	if (check_acl (acl_who,ACL_DETECT, (*ent_p)->e_acl->ac_child, object) == NOTOK) {
		err->dse_type = DSE_SECURITYERROR;
		err->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
		return (DS_X500_ERROR);
	}

	return (DS_OK);
}
示例#9
0
int 
do_ds_read (struct ds_read_arg *arg, struct DSError *error, struct ds_read_result *result, DN binddn, DN target, struct di_block **di_p, int dsp, int quipu_ctx, int authtype)
{
	Entry  entryptr;
	int retval;
#ifdef NOTUSED
	int authenticated;
#endif
	DN realtarget;
	char authp;

	DLOG (log_dsap,LLOG_TRACE,("ds_read"));

	if (!dsp)
		target = arg->rda_object;

	if (!dsp && dsa_read_control(arg,result))
		return (DS_OK);

	if (target == NULLDN) {
		/* can't read from the root */
		error->dse_type = DSE_NAMEERROR;
		error->ERR_NAME.DSE_na_problem = DSE_NA_NOSUCHOBJECT;
		error->ERR_NAME.DSE_na_matched = NULLDN;
		return (DS_ERROR_REMOTE);
	}

	switch(find_entry(target,&(arg->rda_common),binddn,NULLDNSEQ,FALSE,&(entryptr), error, di_p, OP_READ)) {
	case DS_OK:
		/* Filled out entryptr - carry on */
		break;
	case DS_CONTINUE:
		/* Filled out di_p - what do we do with it ?? */
		return(DS_CONTINUE);

	case DS_X500_ERROR:
		/* Filled out error - what do we do with it ?? */
		return(DS_X500_ERROR);
	default:
		/* SCREAM */
		LLOG(log_dsap, LLOG_EXCEPTIONS, ("do_ds_read() - find_entry failed"));
		return(DS_ERROR_LOCAL);
	}

	realtarget = get_copy_dn (entryptr);

	/* User can be authenticated by using strong authentication for this
	 * operation, or by using the credntials from the bind.
	 */

	if (!manager(binddn))
		authp = entryptr->e_authp ? entryptr->e_authp->ap_readandcompare
				: AP_SIMPLE;
	else
		authp = AP_SIMPLE;

#ifdef NOTUSED
	authenticated = 0;

	/* Credentials provided in the ds_bind */
	if ((bind_policy & POLICY_ACCESS_READ) && (!dsp) && (binddn != NULLDN))
		authenticated = 1;
#endif

	/* Strong authentication  */
	/* If it's there, check it, even if you won't believe it anyway */
	if ((retval = check_security_parms((caddr_t) arg,
									   _ZReadArgumentDataDAS,
									   &_ZDAS_mod,
									   arg->rda_common.ca_security,
									   arg->rda_common.ca_sig, &binddn)) != 0) {
		error->dse_type = DSE_SECURITYERROR;
		error->ERR_SECURITY.DSE_sc_problem = retval;
		dn_free (realtarget);
		return (DS_ERROR_REMOTE);
	}

#ifdef NOTUSED
	if ((strong_policy & POLICY_ACCESS_READ) &&
			(arg->rda_common.ca_sig != (struct signature *) 0))
		authenticated = 1;
#endif

	/* entry has got a full list of attributes,  eventually
	   select one required */
	if (check_acl ((authtype % 3) >= authp ? binddn : NULLDN, ACL_READ,
				   entryptr->e_acl->ac_entry, realtarget) == NOTOK) {
		if (dsp && (check_acl (binddn,ACL_READ,entryptr->e_acl->ac_entry, realtarget) == OK)) {
			error->dse_type = DSE_SECURITYERROR;
			error->ERR_SECURITY.DSE_sc_problem = DSE_SC_AUTHENTICATION;
			dn_free (realtarget);
			return (DS_ERROR_REMOTE);
		} else {
			error->dse_type = DSE_SECURITYERROR;
			error->ERR_SECURITY.DSE_sc_problem = DSE_SC_ACCESSRIGHTS;
			dn_free (realtarget);
			return (DS_ERROR_REMOTE);
		}
	}

	if (entryptr->e_dsainfo && need_pseudo_dsa(entryptr,arg)) {

		/* Its a 7.0 or better DSA.
		 * pseudo attributes asked for.
		 * special routing req'd
		         */

		if (dn_cmp (realtarget, mydsadn) == 0) {
			/* Its me - generate result */

			if ((result->rdr_entry.ent_attr = dsa_eis_select (
												  arg->rda_eis,entryptr, dsp ? NULLDN : binddn,
												  quipu_ctx, realtarget)) != NULLATTR)
				goto out;

			if ( arg->rda_eis.eis_allattributes || arg->rda_eis.eis_select == NULLATTR)
				goto out;

			error->dse_type = DSE_ATTRIBUTEERROR;
			error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (entryptr);
			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE;
			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy(arg->rda_eis.eis_select->attr_type);
			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
			error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
			dn_free (realtarget);
			return (DS_ERROR_REMOTE);

		} else {
			/* make referral to DSA in this entry */
			(*di_p) = di_alloc();
			(*di_p)->di_type = DI_TASK;
			(*di_p)->di_dn = realtarget;
			(*di_p)->di_target = dn_cpy(realtarget);
			(*di_p)->di_reftype = RT_UNDEFINED;
			(*di_p)->di_rdn_resolved = CR_RDNRESOLVED_NOTDEFINED;
			(*di_p)->di_aliasedRDNs = CR_NOALIASEDRDNS;
			(*di_p)->di_entry = entryptr;
			entryptr->e_refcount++;
			(*di_p)->di_state = DI_COMPLETE;

			return DS_CONTINUE;
		}

	}

	if (cant_use_cache (entryptr,binddn,arg->rda_eis,realtarget)) {
		int res =  referral_dsa_info(realtarget,NULLDNSEQ,FALSE,entryptr,error,di_p,
									 arg->rda_common.ca_servicecontrol.svc_options & SVC_OPT_PREFERCHAIN);
		dn_free (realtarget);
		return res;
	}

	if (dsp && (eis_check (arg->rda_eis,entryptr, binddn) != OK)) {
		/* Can only send public things over DSP - but user is entitled to more */
		error->dse_type = DSE_SECURITYERROR;
		error->ERR_SECURITY.DSE_sc_problem = DSE_SC_AUTHENTICATION;
		dn_free (realtarget);
		return (DS_ERROR_REMOTE);
	}

	if ((result->rdr_entry.ent_attr = eis_select (arg->rda_eis,entryptr, dsp ? NULLDN : binddn, quipu_ctx, realtarget)) == NULLATTR)
		if ( !arg->rda_eis.eis_allattributes && arg->rda_eis.eis_select != NULLATTR) {
			error->dse_type = DSE_ATTRIBUTEERROR;
			error->ERR_ATTRIBUTE.DSE_at_name = get_copy_dn (entryptr);
			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_what =DSE_AT_NOSUCHATTRIBUTE;
			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_type = AttrT_cpy(arg->rda_eis.eis_select->attr_type);
			error->ERR_ATTRIBUTE.DSE_at_plist.DSE_at_value = NULLAttrV;
			error->ERR_ATTRIBUTE.DSE_at_plist.dse_at_next = DSE_AT_NOPROBLEM;
			dn_free (realtarget);
			return (DS_ERROR_REMOTE);
		}

out:
	;
	result->rdr_entry.ent_dn = realtarget;
	result->rdr_entry.ent_iscopy = entryptr->e_data;
	result->rdr_entry.ent_age = (time_t) 0;
	result->rdr_entry.ent_next = NULLENTRYINFO;
	result->rdr_common.cr_requestor = NULLDN;
	/* if no error and NOT SVC_OPT_DONTDEREFERENCEALIASES then */
	/* the alias will have been derefeferenced -signified by   */
	/* NO_ERROR !!! */
	result->rdr_common.cr_aliasdereferenced = (error->dse_type == DSE_NOERROR) ? FALSE : TRUE;
	return (DS_OK);

}
示例#10
0
文件: pcpd.c 项目: zixia/nospam
static int doline(struct PCP *pcp, char *p, int acl_flags)
{
	char *q=strtok(p, " ");

	if (!q)
	{
		printf("500 Syntax error\n");
		return (0);
	}

	if (strcasecmp(q, "QUIT") == 0)
	{
		printf("200 Bye.\n");
		return (-1);
	}

	if (strcasecmp(q, "NOOP") == 0)
	{
		printf("200 Ok.\n");
		return (0);
	}

	if (strcasecmp(q, "CAPABILITY") == 0)
	{
		printf("100-ACL\n");
		printf("100 PCP1\n");
		return (0);
	}

	if (strcasecmp(q, "LIST") == 0)
	{
		if (check_acl(acl_flags, PCP_ACL_LIST))
			return (0);

		if (list(pcp))
			printf("500 Syntax error\n");
		return (0);
	}

	if (strcasecmp(q, "RETR") == 0)
	{
		if (check_acl(acl_flags, PCP_ACL_RETR))
			return (0);

		if (retr(pcp))
			printf("500 Syntax error\n");
		return (0);
	}


	if (strcasecmp(q, "ACL") == 0 && pcp_has_acl(pcp) && !proxy_userid)
	{
		q=strtok(NULL, " ");
		if (q && strcasecmp(q, "SET") == 0)
		{
			const char *who=strtok(NULL, " ");

			if (who)
			{
				int flags=0;

				while ((q=strtok(NULL, " ")) != 0)
					flags |= pcp_acl_num(q);

				if (pcp_acl(pcp, who, flags))
				{
					error(0);
					return (0);
				}
				printf("200 Ok\n");
				return (0);
			}
		}
		else if (q && strcasecmp(q, "LIST") == 0)
		{
			listacls(pcp);
			return (0);
		}
	}

	if (strcasecmp(q, "RSET") == 0)
	{
		conflict_flag=0;
		force_flag=0;
		need_rset=0;
		rset(pcp);
		printf("200 Ok.\n");	
		return (0);
	}

	if (need_rset)
	{
		printf("500 RSET required - calendar in an unknown state.\n");
		return (0);
	}

	if (strcasecmp(q, "DELETE") == 0)
	{
		struct PCP_retr r;
		const char *event_id_list[2];

		char *e=strtok(NULL, " ");

		if (check_acl(acl_flags, PCP_ACL_MODIFY))
			return (0);

		if (e && deleted_eventid == NULL && new_eventid == NULL)
		{
			if ((deleted_eventid=strdup(e)) == NULL)
			{
				perror("strdup");
				exit(1);
			}
			proxy_list_rset();
			memset(&r, 0, sizeof(r));
			r.callback_retr_participants=open_event_participant;
			event_id_list[0]=deleted_eventid;
			event_id_list[1]=NULL;
			r.event_id_list=event_id_list;
			if (pcp_retr(pcp, &r))
			{
				error(r.errcode);
				proxy_list_rset();
			}
			else
				printf("200 Ok.\n");
			return (0);
		}
	}

	if (strcasecmp(q, "NEW") == 0 && new_eventid == NULL)
	{
		if (check_acl(acl_flags, PCP_ACL_MODIFY))
			return (0);

		new_eventid=readnewevent(pcp);

		if (new_eventid == NULL)
		{
			printf("500 %s\n", strerror(errno));
		}
		else
			printf("109 %s ready to be commited.\n",
			       new_eventid->eventid);
		return (0);
	}

	if (strcasecmp(q, "BOOK") == 0 && new_eventid)
	{
		dobook(pcp);
		return (0);
	}

	if (strcasecmp(q, "CONFLICT") == 0)
	{
		q=strtok(NULL, " ");
		if (q && strcasecmp(q, "ON") == 0)
		{
			if (check_acl(acl_flags, PCP_ACL_CONFLICT))
				return (0);

			conflict_flag=1;
		}
		else
			conflict_flag=0;
		printf("200 Ok.\n");
		return (0);
	}

	if (strcasecmp(q, "FORCE") == 0)
	{
		q=strtok(NULL, " ");
		if (q && strcasecmp(q, "ON") == 0)
		{
			force_flag=1;
		}
		else
			force_flag=0;
		printf("200 Ok.\n");
		return (0);
	}

	if (strcasecmp(q, "COMMIT") == 0)
	{
		if (notbooked)
		{
			printf("500 BOOK required.\n");
		}
		else if (new_eventid && new_commit_times)
		{
			struct proxy_list *pl;

			new_commit.add_conflict_callback=NULL;
			new_commit.add_conflict_callback_ptr=NULL;

			new_commit.flags=
				(conflict_flag ? PCP_OK_CONFLICT:0) |
				(force_flag ? PCP_OK_PROXY_ERRORS:0);

			for (pl=proxy_list; pl; pl=pl->next)
			{
				if (pl->flags & PROXY_IGNORE)
					continue;

				if (pl->flags & PROXY_NEW)
				{
					if (pcp_commit(pl->proxy,
						       pl->newevent,
						       &new_commit))
					{
						syslog(LOG_CRIT,
						       "COMMIT failed for PROXY %s",
						       pl->userid);

						if (!force_flag)
						{
							pl->flags &=
								~PROXY_NEW;
							error(new_commit
							      .errcode);
							return (0);
						}
					}
				}
				else if (pl->old_event_id)
				{
					struct PCP_delete del;

					memset(&del, 0, sizeof(del));

					del.id=pl->old_event_id;

					if (pcp_delete(pl->proxy, &del))
					{
						syslog(LOG_CRIT,
						       "DELETE failed for PROXY %s",
						       pl->userid);
						if (!force_flag)
						{
							error(del.errcode);
							return (0);
						}
						pl->flags |= PROXY_IGNORE;
					}
				}
			}

			if (proxy_userid)
				new_commit.flags |= PCP_BYPROXY;

			if (pcp_commit(pcp, new_eventid, &new_commit))
				error(new_commit.errcode);
			else
			{
				const char *proxy_name=NULL;
				const char *proxy_action=NULL;

				for (pl=proxy_list; pl; pl=pl->next)
				{
					if (proxy_name)
						printf("111-%s %s\n",
						       proxy_action,
						       proxy_name);

					proxy_action=
						!(pl->flags & PROXY_IGNORE)
						&& (pl->flags & PROXY_NEW)
						? "NEW":"DELETE";
					proxy_name=pl->userid;
				}

				if (proxy_name)
					printf("111 %s %s\n",
					       proxy_action,
					       proxy_name);
				else
					printf("200 Ok.\n");
			}	
			rset(pcp);
			return (0);
		}
		else if (!new_eventid && deleted_eventid)
		{
			struct proxy_list *pl;
			struct PCP_delete del;
			const char *proxy_userid;

			for (pl=proxy_list; pl; pl=pl->next)
			{
				if (pl->flags & PROXY_IGNORE)
					continue;

				if (pl->old_event_id)
				{
					memset(&del, 0, sizeof(del));
					del.id=pl->old_event_id;

					if (pcp_delete(pl->proxy, &del))
					{
						syslog(LOG_CRIT,
						       "DELETE failed for PROXY %s",
						       pl->userid);
					}
				}
			}

			memset(&del, 0, sizeof(del));
			del.id=deleted_eventid;

			if (pcp_delete(pcp, &del))
			{
				if (del.errcode != PCP_ERR_EVENTNOTFOUND)
				{
					error(del.errcode);
					return (0);
				}
			}

			proxy_userid=NULL;
			for (pl=proxy_list; pl; pl=pl->next)
			{
				if (proxy_userid)
					printf("111-DELETE %s\n",
					       proxy_userid);

				proxy_userid=pl->userid;
			}

			if (proxy_userid)
				printf("111 DELETE %s\n", proxy_userid);
			else
				printf("200 Ok\n");

			rset(pcp);
			return (0);
		}

		printf("500 There's nothing to commit.\n");
		return (0);
	}

	if (strcasecmp(q, "CANCEL") == 0)
	{
		int errcode;

		if (check_acl(acl_flags, PCP_ACL_MODIFY))
			return (0);

		q=strtok(NULL, " ");
		if (!q)
			printf("500 Syntax error\n");
		else if (pcp_cancel(pcp, q, &errcode))
			error(errcode);
		else
			printf("200 Cancelled\n");
		return (0);
	}

	if (strcasecmp(q, "UNCANCEL") == 0)
	{
		struct PCP_uncancel unc;
		struct uncancel_list *list=NULL, **tail= &list;
		struct uncancel_list *p;

		if (check_acl(acl_flags, PCP_ACL_MODIFY))
			return (0);

		memset(&unc, 0, sizeof(unc));
		unc.uncancel_conflict_callback=uncancel_callback;
		unc.uncancel_conflict_callback_ptr=&tail;

		q=strtok(NULL, " ");
		if (!q)
			printf("500 Syntax error\n");
		else if (pcp_uncancel(pcp, q,
				      (conflict_flag ? PCP_OK_CONFLICT:0)|
				      (force_flag ? PCP_OK_PROXY_ERRORS:0),
				      &unc))
		{
			if (unc.errcode == PCP_ERR_CONFLICT && list)
			{
				for (p=list; p; p=p->next)
				{
					char from_buf[15];
					char to_buf[15];

					pcp_gmtimestr(p->from, from_buf);
					pcp_gmtimestr(p->to, to_buf);

					printf("403%c%s %s %s %s conflicts.\n",
					       p->next ? '-':' ',
					       p->addr,
					       from_buf,
					       to_buf,
					       p->id);
				}
			}
			else
				error(unc.errcode);
		}
		else
			printf("200 Uncancelled\n");

		while((p=list) != NULL)
		{
			list=p->next;
			free(p->addr);
			free(p->id);
			free(p);
		}
		return (0);
	}

	printf("500 Syntax error\n");
	return (0);
}