/*
- * rlm_exe.c
+ * rlm_exec.c
*
* Version: $Id$
*
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*
- * Copyright 2002 The FreeRADIUS server project
+ * Copyright 2002,2006 The FreeRADIUS server project
* Copyright 2002 Alan DeKok <aland@ox.org>
*/
-#include <freeradius-devel/autoconf.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
+#include <freeradius-devel/ident.h>
+RCSID("$Id$")
#include <freeradius-devel/radiusd.h>
#include <freeradius-devel/modules.h>
-#include <freeradius-devel/conffile.h>
-
-static const char rcsid[] = "$Id$";
/*
* Define a structure for our module configuration.
*/
typedef struct rlm_exec_t {
char *xlat_name;
+ int bare;
int wait;
char *program;
char *input;
return &request->reply->vps;
}
+#ifdef WITH_PROXY
if (strcmp(string, "proxy-request") == 0) {
if (!request->proxy) return NULL;
return &request->proxy_reply->vps;
}
+#endif
if (strcmp(string, "config") == 0) {
return &request->config_items;
/*
* Do xlat of strings.
*/
-static int exec_xlat(void *instance, REQUEST *request,
- char *fmt, char *out, int outlen,
+static size_t exec_xlat(void *instance, REQUEST *request,
+ char *fmt, char *out, size_t outlen,
UNUSED RADIUS_ESCAPE_STRING func)
{
int result;
rlm_exec_t *inst = instance;
VALUE_PAIR **input_pairs;
+ char *p;
input_pairs = decode_string(request, inst->input);
if (!input_pairs) {
/*
* FIXME: Do xlat of program name?
*/
- DEBUG2("rlm_exec (%s): Executing %s", inst->xlat_name, fmt);
+ RDEBUG2("Executing %s", fmt);
result = radius_exec_program(fmt, request, inst->wait,
out, outlen, *input_pairs, NULL, inst->shell_escape);
- DEBUG2("rlm_exec (%s): result %d", inst->xlat_name, result);
+ RDEBUG2("result %d", result);
if (result != 0) {
out[0] = '\0';
return 0;
}
+ for (p = out; *p != '\0'; p++) {
+ if (*p < ' ') *p = ' ';
+ }
+
return strlen(out);
}
free(inst->xlat_name);
}
- /*
- * Free the strings.
- */
- if (inst->program) free(inst->program);
- if (inst->input) free(inst->input);
- if (inst->output) free(inst->output);
- if (inst->packet_type) free(inst->packet_type);
-
free(inst);
return 0;
}
}
/*
- * Sanity check the config. If we're told to wait,
- * then the output pairs should be defined.
- */
- if (inst->wait &&
- (inst->output == NULL)) {
- radlog(L_INFO, "rlm_exec: wait=yes but no output defined. Did you mean output=none?");
- }
-
- /*
* Get the packet type on which to execute
*/
if (!inst->packet_type) {
} else {
DICT_VALUE *dval;
- dval = dict_valbyname(PW_PACKET_TYPE, inst->packet_type);
+ dval = dict_valbyname(PW_PACKET_TYPE, 0, inst->packet_type);
if (!dval) {
radlog(L_ERR, "rlm_exec: Unknown packet type %s: See list of VALUEs for Packet-Type in share/dictionary", inst->packet_type);
exec_detach(inst);
}
xlat_name = cf_section_name2(conf);
- if (xlat_name == NULL)
+ if (xlat_name == NULL) {
xlat_name = cf_section_name1(conf);
+ inst->bare = 1;
+ }
if (xlat_name){
inst->xlat_name = strdup(xlat_name);
xlat_register(xlat_name, exec_xlat, inst);
*/
if (!((inst->packet_code == 0) ||
(request->packet->code == inst->packet_code) ||
- (request->reply->code == inst->packet_code) ||
- (request->proxy &&
+ (request->reply->code == inst->packet_code)
+#ifdef WITH_PROXY
+ || (request->proxy &&
(request->proxy->code == inst->packet_code)) ||
(request->proxy_reply &&
- (request->proxy_reply->code == inst->packet_code)))) {
- DEBUG2(" rlm_exec (%s): Packet type is not %s. Not executing.",
- inst->xlat_name, inst->packet_type);
+ (request->proxy_reply->code == inst->packet_code))
+#endif
+ )) {
+ RDEBUG2("Packet type is not %s. Not executing.",
+ inst->packet_type);
return RLM_MODULE_NOOP;
}
input_pairs = decode_string(request, inst->input);
output_pairs = decode_string(request, inst->output);
+ if (!input_pairs) {
+ RDEBUG2("WARNING: Possible parse error in %s",
+ inst->input);
+ return RLM_MODULE_NOOP;
+ }
+
/*
* It points to the attribute list, but the attribute
* list is empty.
*/
- if (input_pairs && !*input_pairs) {
- DEBUG2("rlm_exec (%s): WARNING! Input pairs are empty. No attributes will be passed to the script", inst->xlat_name);
+ if (!*input_pairs) {
+ RDEBUG2("WARNING! Input pairs are empty. No attributes will be passed to the script");
}
/*
VALUE_PAIR *vp, *tmp;
rlm_exec_t *inst = (rlm_exec_t *) instance;
- vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM);
+ vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM, 0);
if (vp) {
exec_wait = 0;
- } else if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT)) != NULL) {
+ } else if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT, 0)) != NULL) {
exec_wait = 1;
}
- if (!vp) goto dispatch;
+ if (!vp) {
+ if (!inst->program) return RLM_MODULE_NOOP;
+
+ return exec_dispatch(instance, request);
+ }
tmp = NULL;
result = radius_exec_program(vp->vp_strvalue, request, exec_wait,
*/
tmp = pairmake("Reply-Message", "Access denied (external check failed)", T_OP_SET);
pairadd(&request->reply->vps, tmp);
-
- DEBUG2("Login incorrect (external check failed)");
+
+ RDEBUG2("Login incorrect (external check failed)");
request->reply->code = PW_AUTHENTICATION_REJECT;
return RLM_MODULE_REJECT;
* exit status.
*/
request->reply->code = PW_AUTHENTICATION_REJECT;
- DEBUG2("Login incorrect (external check said so)");
+ RDEBUG2("Login incorrect (external check said so)");
return RLM_MODULE_REJECT;
}
- dispatch:
- if (!inst->program) return RLM_MODULE_NOOP;
+ return RLM_MODULE_OK;
+}
+
+/*
+ * First, look for Exec-Program && Exec-Program-Wait.
+ *
+ * Then, call exec_dispatch.
+ */
+static int exec_accounting(void *instance, REQUEST *request)
+{
+ int result;
+ int exec_wait = 0;
+ VALUE_PAIR *vp;
+ rlm_exec_t *inst = (rlm_exec_t *) instance;
+
+ /*
+ * The "bare" exec module takes care of handling
+ * Exec-Program and Exec-Program-Wait.
+ */
+ if (!inst->bare) return exec_dispatch(instance, request);
+
+ vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM, 0);
+ if (vp) {
+ exec_wait = 0;
+
+ } else if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT, 0)) != NULL) {
+ exec_wait = 1;
+ }
+ if (!vp) return RLM_MODULE_NOOP;
+
+ result = radius_exec_program(vp->vp_strvalue, request, exec_wait,
+ NULL, 0, request->packet->vps, NULL,
+ inst->shell_escape);
+ if (result != 0) {
+ return RLM_MODULE_REJECT;
+ }
- return exec_dispatch(instance, request);
+ return RLM_MODULE_OK;
}
/*
module_t rlm_exec = {
RLM_MODULE_INIT,
"exec", /* Name */
- RLM_TYPE_THREAD_SAFE, /* type */
+ RLM_TYPE_CHECK_CONFIG_SAFE, /* type */
exec_instantiate, /* instantiation */
exec_detach, /* detach */
{
exec_dispatch, /* authentication */
exec_dispatch, /* authorization */
exec_dispatch, /* pre-accounting */
- exec_dispatch, /* accounting */
+ exec_accounting, /* accounting */
NULL, /* check simul */
exec_dispatch, /* pre-proxy */
exec_dispatch, /* post-proxy */
exec_postauth /* post-auth */
+#ifdef WITH_COA
+ , exec_dispatch,
+ exec_dispatch
+#endif
},
};