Re-implemented Exec-Program && Exec-Program-Wait in rlm_exec,
authoraland <aland>
Mon, 28 Nov 2005 21:47:01 +0000 (21:47 +0000)
committeraland <aland>
Mon, 28 Nov 2005 21:47:01 +0000 (21:47 +0000)
in the post-auth section.

We may want to add this in the "accounting" section, too

share/dictionary.freeradius.internal
src/include/radius.h
src/modules/rlm_exec/rlm_exec.c

index d42ba73..30b3134 100644 (file)
@@ -12,6 +12,8 @@
 
 #      These attributes CAN go in the reply item list.
 ATTRIBUTE      Fall-Through                            500     integer
+ATTRIBUTE      Exec-Program                            502     string
+ATTRIBUTE      Exec-Program-Wait                       503     string
 
 #      These attributes CANNOT go in the reply item list.
 
index 2ac68ad..f1aa0a2 100644 (file)
 #define PW_DIGEST_ATTRIBUTES           207
 
 #define PW_FALL_THROUGH                        500
+#define PW_EXEC_PROGRAM                        502
+#define PW_EXEC_PROGRAM_WAIT           503
 
 #define PW_AUTH_TYPE                   1000
 #define PW_PREFIX                      1003
index d2f9f2a..5b7ebab 100644 (file)
@@ -43,7 +43,7 @@ typedef struct rlm_exec_t {
        char    *input;
        char    *output;
        char    *packet_type;
-       int     packet_code;
+       unsigned int    packet_code;
        int     shell_escape;
 } rlm_exec_t;
 
@@ -359,6 +359,68 @@ static int exec_dispatch(void *instance, REQUEST *request)
 
 
 /*
+ *     First, look for Exec-Program && Exec-Program-Wait.
+ *
+ *     Then, call exec_dispatch.
+ */
+static int exec_postauth(void *instance, REQUEST *request)
+{
+       int result;
+       int exec_wait = 0;
+       VALUE_PAIR *vp, *tmp;
+       rlm_exec_t *inst = (rlm_exec_t *) instance;
+
+       vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM);
+       if (vp) {
+               exec_wait = 0;
+
+       } else if ((vp = pairfind(request->reply->vps, PW_EXEC_PROGRAM_WAIT)) != NULL) {
+               exec_wait = 1;
+       }
+       if (!vp) goto dispatch;
+
+       tmp = NULL;
+       result = radius_exec_program(vp->vp_strvalue, request, exec_wait,
+                                    NULL, 0, request->packet->vps, &tmp,
+                                    inst->shell_escape);
+
+       /*
+        *      Always add the value-pairs to the reply.
+        */
+       pairmove(&request->reply->vps, &tmp);
+       pairfree(&tmp);
+
+       if (result < 0) {
+               /*
+                *      Error. radius_exec_program() returns -1 on
+                *      fork/exec errors.
+                */
+               tmp = pairmake("Reply-Message", "Access denied (external check failed)", T_OP_SET);
+               pairadd(&request->reply->vps, tmp);
+               
+               DEBUG2("Login incorrect (external check failed)");
+
+               request->reply->code = PW_AUTHENTICATION_REJECT;
+               return RLM_MODULE_REJECT;
+       }
+       if (result > 0) {
+               /*
+                *      Reject. radius_exec_program() returns >0
+                *      if the exec'ed program had a non-zero
+                *      exit status.
+                */
+               request->reply->code = PW_AUTHENTICATION_REJECT;
+               DEBUG2("Login incorrect (external check said so)");
+               return RLM_MODULE_REJECT;
+       }
+
+ dispatch:
+       if (!inst->program) return RLM_MODULE_NOOP;
+
+       return exec_dispatch(instance, request);
+}
+
+/*
  *     The module name should be the only globally exported symbol.
  *     That is, everything else should be 'static'.
  *
@@ -381,6 +443,6 @@ module_t rlm_exec = {
                NULL,                   /* check simul */
                exec_dispatch,          /* pre-proxy */
                exec_dispatch,          /* post-proxy */
-               exec_dispatch           /* post-auth */
+               exec_postauth           /* post-auth */
        },
 };