1/*++
2/* NAME
3/*	local_expand 3
4/* SUMMARY
5/*	set up attribute list for $name expansion
6/* SYNOPSIS
7/*	#include "local.h"
8/*
9/*	int	local_expand(result, pattern, state, usr_attr, filter)
10/*	VSTRING	*result;
11/*	const	char *pattern;
12/*	LOCAL_STATE state;
13/*	USER_ATTR usr_attr;
14/*	const char *filter;
15/* DESCRIPTION
16/*	local_expand() performs conditional and unconditional $name
17/*	expansion based on message delivery attributes.
18/*	The result is the bitwise OR or zero or more of the following:
19/* .IP LOCAL_EXP_EXTENSION_MATCHED
20/*	The result of expansion contains the $extension attribute.
21/* .IP MAC_PARSE_XXX
22/*	See mac_parse(3).
23/* .PP
24/*	Attributes:
25/* .IP client_address
26/*	The client network address.
27/* .IP client_helo
28/*	The client HELO command parameter.
29/* .IP client_hostname
30/*	The client hostname.
31/* .IP client_protocol
32/*	The client protocol.
33/* .IP domain
34/*	The recipient address domain.
35/* .IP extension
36/*	The recipient address extension.
37/* .IP home
38/*	The recipient home directory.
39/* .IP local
40/*	The entire recipient address localpart.
41/* .IP recipient
42/*	The entire recipient address.
43/* .IP recipient_delimiter
44/*	The recipient delimiter.
45/* .IP shell
46/*	The recipient shell program.
47/* .IP sasl_method
48/*	The SASL authentication method.
49/* .IP sasl_sender
50/*	The SASL MAIL FROM address.
51/* .IP sasl_username
52/*	The SASL login name.
53/* .IP user
54/*	The recipient user name.
55/* .PP
56/*	Arguments:
57/* .IP result
58/*	Storage for the result of expansion. The buffer is truncated
59/*	upon entry.
60/* .IP pattern
61/*	The string with unconditional and conditional macro expansions.
62/* .IP state
63/*	Message delivery attributes (sender, recipient etc.).
64/*	Attributes describing alias, include or forward expansion.
65/*	A table with the results from expanding aliases or lists.
66/*	A table with delivered-to: addresses taken from the message.
67/* .IP usr_attr
68/*	Attributes describing user rights and environment.
69/* .IP filter
70/*	A null pointer, or a string of allowed characters in $name
71/*	expansions. Illegal characters are replaced by underscores.
72/* DIAGNOSTICS
73/*	Fatal errors: out of memory.
74/* SEE ALSO
75/*	mac_expand(3) macro expansion
76/* LICENSE
77/* .ad
78/* .fi
79/*	The Secure Mailer license must be distributed with this software.
80/* AUTHOR(S)
81/*	Wietse Venema
82/*	IBM T.J. Watson Research
83/*	P.O. Box 704
84/*	Yorktown Heights, NY 10598, USA
85/*--*/
86
87/* System library. */
88
89#include <sys_defs.h>
90#include <string.h>
91
92/* Utility library. */
93
94#include <vstring.h>
95#include <mac_expand.h>
96
97/* Global library */
98
99#include <mail_params.h>
100
101/* Application-specific. */
102
103#include "local.h"
104
105typedef struct {
106    LOCAL_STATE *state;
107    USER_ATTR *usr_attr;
108    int     status;
109} LOCAL_EXP;
110
111/* local_expand_lookup - mac_expand() lookup routine */
112
113static const char *local_expand_lookup(const char *name, int mode, char *ptr)
114{
115    LOCAL_EXP *local = (LOCAL_EXP *) ptr;
116    static char rcpt_delim[2];
117
118#define STREQ(x,y) (*(x) == *(y) && strcmp((x), (y)) == 0)
119
120    if (STREQ(name, "user")) {
121	return (local->state->msg_attr.user);
122    } else if (STREQ(name, "home")) {
123	return (local->usr_attr->home);
124    } else if (STREQ(name, "shell")) {
125	return (local->usr_attr->shell);
126    } else if (STREQ(name, "domain")) {
127	return (local->state->msg_attr.domain);
128    } else if (STREQ(name, "local")) {
129	return (local->state->msg_attr.local);
130    } else if (STREQ(name, "mailbox")) {
131	return (local->state->msg_attr.local);
132    } else if (STREQ(name, "recipient")) {
133	return (local->state->msg_attr.rcpt.address);
134    } else if (STREQ(name, "extension")) {
135	if (mode == MAC_EXP_MODE_USE)
136	    local->status |= LOCAL_EXP_EXTENSION_MATCHED;
137	return (local->state->msg_attr.extension);
138    } else if (STREQ(name, "recipient_delimiter")) {
139	rcpt_delim[0] =
140	    local->state->msg_attr.local[strlen(local->state->msg_attr.user)];
141	rcpt_delim[1] = 0;
142	return (rcpt_delim[0] ? rcpt_delim : 0);
143#if 0
144    } else if (STREQ(name, "client_hostname")) {
145	return (local->state->msg_attr.request->client_name);
146    } else if (STREQ(name, "client_address")) {
147	return (local->state->msg_attr.request->client_addr);
148    } else if (STREQ(name, "client_protocol")) {
149	return (local->state->msg_attr.request->client_proto);
150    } else if (STREQ(name, "client_helo")) {
151	return (local->state->msg_attr.request->client_helo);
152    } else if (STREQ(name, "sasl_method")) {
153	return (local->state->msg_attr.request->sasl_method);
154    } else if (STREQ(name, "sasl_sender")) {
155	return (local->state->msg_attr.request->sasl_sender);
156    } else if (STREQ(name, "sasl_username")) {
157	return (local->state->msg_attr.request->sasl_username);
158#endif
159    } else {
160	return (0);
161    }
162}
163
164/* local_expand - expand message delivery attributes */
165
166int     local_expand(VSTRING *result, const char *pattern,
167	        LOCAL_STATE *state, USER_ATTR *usr_attr, const char *filter)
168{
169    LOCAL_EXP local;
170    int     expand_status;
171
172    local.state = state;
173    local.usr_attr = usr_attr;
174    local.status = 0;
175    expand_status = mac_expand(result, pattern, MAC_EXP_FLAG_NONE,
176			       filter, local_expand_lookup, (char *) &local);
177    return (local.status | expand_status);
178}
179