]> granicus.if.org Git - fcron/commitdiff
limit number of authentification failures
authorthib <thib>
Sun, 31 Mar 2002 15:06:19 +0000 (15:06 +0000)
committerthib <thib>
Sun, 31 Mar 2002 15:06:19 +0000 (15:06 +0000)
bug corrected and improvements in exe_cmd

socket.c

index 7c1ce777c4e0b243932154187ff0238805cc571b..0c297652f9797d923670199f24fa16e7e19600f1 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -21,7 +21,7 @@
  *  `LICENSE' that comes with the fcron source distribution.
  */
 
- /* $Id: socket.c,v 1.1 2002-03-02 17:29:43 thib Exp $ */
+ /* $Id: socket.c,v 1.2 2002-03-31 15:06:19 thib Exp $ */
 
 /* This file contains all fcron's code (server) to handle communication with fcrondyn */
 
 
 void exe_cmd(struct fcrondyn_cl *client);
 void auth_client(struct fcrondyn_cl *client);
+int print_fields(int fd, char print_user, char print_details);
+int print_line(int fd, struct CL *line, char print_user, char print_details);
 
 fcrondyn_cl *fcrondyn_cl_base; /* list of connected fcrondyn clients */
 int fcrondyn_cl_num = 0;       /* number of fcrondyn clients currently connected */    
 fd_set read_set;               /* client fds list : cmd waiting ? */
 fd_set master_set;             /* master set : needed since select() modify read_set */
 int set_max_fd = 0;            /* needed by select() */
-int listen_fd = -1;          /* fd which catches incoming connection */
-
+int listen_fd = -1;            /* fd which catches incoming connection */
+int auth_fail = 0;             /* number of auth failure */
+time_t auth_nofail_since = 0;       /* we refuse auth since x due to too many failures */
 
 void
 init_socket(void)
@@ -49,6 +52,7 @@ init_socket(void)
 
     /* used in fcron.c:main_loop():select() */
     FD_ZERO(&read_set);
+    FD_ZERO(&master_set);
 
     if ( (listen_fd = socket(PF_UNIX, SOCK_STREAM, 0)) == -1 ) {
        error_e("Could not create socket : fcrondyn won't work");
@@ -126,6 +130,22 @@ auth_client(struct fcrondyn_cl *client)
     pass_sys = pass->pw_passwd;
 #endif
 
+    /* */
+    debug("auth_client() : socket : %d", client->fcl_sock_fd);
+    /* */
+
+    /* we need to limit auth failures : otherwise fcron may be used to "read"
+     * shadow password !!! (or to crack it using a test-all-possible-password attack) */
+    if (auth_fail > 0 && auth_nofail_since + AUTH_WAIT <= now )
+       /* no auth time exceeded : set counter to 0 */
+       auth_fail = 0;
+    if (auth_fail >= MAX_AUTH_FAIL) {
+       error("Too many authentication failures : try to connect later.");
+       send(client->fcl_sock_fd, "0", sizeof("0"), 0);     
+       auth_fail = auth_nofail_since = 0;
+       return;    
+    }
+
     /* password is stored after user name */
     pass_str = &( (char *)client->fcl_cmd ) [ strlen( (char*)client->fcl_cmd ) + 1 ];
     if ( (pass_cry = crypt(pass_str, pass_sys)) == NULL ) {
@@ -141,6 +161,8 @@ auth_client(struct fcrondyn_cl *client)
        send(client->fcl_sock_fd, "1", sizeof("1"), 0);
     }
     else {
+       auth_fail++;
+       auth_nofail_since = now;
        error("Invalid passwd for %s from socket %d",
              (char *) client->fcl_cmd, client->fcl_sock_fd);
        send(client->fcl_sock_fd, "0", sizeof("0"), 0);
@@ -148,56 +170,133 @@ auth_client(struct fcrondyn_cl *client)
 }
 
 
+
+int
+print_fields(int fd, char print_user, char print_details)
+    /* print a line describing the field types used in print_line() */
+{
+    char fields[] =  "  USER ID   SCHEDULE         CMD\n";
+    char fields_details[] = "  USER ID    R&Q SCHEDULE         CMD\n";
+    char *str = NULL;
+    int len = 0;
+
+    str = (print_details) ? fields_details : fields;
+    len = (print_details) ? sizeof(fields_details) : sizeof(fields);
+    if ( ! print_user ) {
+       str += 7;
+       len -= 7;
+    }
+
+    if ( send(fd, str, len, 0) < 0 )
+       error_e("error in send()");
+
+    return OK;
+}
+
+
+int
+print_line(int fd, struct CL *line, char print_user, char print_details)
+    /* print some basic fields of a line, and some more if details == 1 */
+{
+    char buf[LINE_LEN];
+    int len = 0;
+    struct tm *ftime;
+
+
+    ftime = localtime( &(line->cl_nextexe) );
+    len = snprintf(buf, sizeof(buf), "%*s%s%-4ld ",
+                  (print_user) ? 6 : 0, (print_user) ? line->cl_file->cf_user : "",
+                  (print_user) ? " " : "",
+                  line->cl_id);
+    if (print_details)
+       len += snprintf(buf+len, sizeof(buf)-len, "%4d ", line->cl_numexe);
+    len += snprintf(buf+len, sizeof(buf)-len, "%02d/%02d/%d %02d:%02d %s\n",
+                  (ftime->tm_mon + 1), ftime->tm_mday, (ftime->tm_year + 1900),
+                  ftime->tm_hour, ftime->tm_min,
+                  line->cl_shell);
+
+    if ( send(fd, buf, len + 1, 0) < 0 )
+       error_e("error in send()");
+
+    return OK;
+    
+}
+
+
 void
 exe_cmd(struct fcrondyn_cl *client)
     /* read command, and call corresponding function */
 {
-    char buf[LINE_LEN];
-    int len = 0;
+    long int *cmd;
+    int fd;
+    char not_found_str[] = "No corresponding job found.\n";
+    char not_allowed_str[] = "You are not allowed to see/change this line.\n";
+    char cmd_unknown_str[] = "Not implemented yet or erroneous command.\n";
+    char details = 0;
+    char found = 0;
+    char is_root = 0;
+
+    /* to make seems clearer (avoid repeating client->fcl_ all the time */
+    cmd = client->fcl_cmd;
+    fd = client->fcl_sock_fd;
+
+    /* */
+    debug("exe_cmd [0,1,2] : %d %d %d", cmd[0], cmd[1], cmd[2]);
+    /* */
 
     switch ( client->fcl_cmd[0] ) {
+    case CMD_DETAILS:
+       details = 1;
     case CMD_LIST_JOBS:
     {
        struct job *j;
-       debug("client->fcl_cmd[1,2,3] : %d %d %d", client->fcl_cmd[0], client->fcl_cmd[1], client->fcl_cmd[2]);
-       if ( client->fcl_cmd[1] == ALL && strcmp(client->fcl_user, ROOTNAME) != 0) {
+       char all = (client->fcl_cmd[1] == ALL) ? 1 : 0;
+
+       is_root = (strcmp(client->fcl_user, ROOTNAME) == 0) ? 1 : 0;
+       if ( all && ! is_root) {
            warn("User %s tried to list *all* jobs.", client->fcl_user);
-           send(client->fcl_sock_fd, "you are not allowed to list all jobs.\n",
+           send(fd, "you are not allowed to list all jobs.\n",
                 sizeof("you are not allowed to list all jobs.\n"), 0);
-           send(client->fcl_sock_fd, END_STR, sizeof(END_STR), 0);
+           send(fd, END_STR, sizeof(END_STR), 0);
            return;
        }
-       send(client->fcl_sock_fd, "Listing jobs :\n", sizeof("Listing jobs :\n"), 0);
-       send(client->fcl_sock_fd, "ID\tCMD\t\n", sizeof("ID\tCMD\t\n"), 0);
-       for ( j = queue_base; j != NULL; j = j->j_next ) {
-           if ( client->fcl_cmd[1] == ALL ||
-                strcmp(client->fcl_user, j->j_line->cl_file->cf_user) == 0 ) {
-               len = snprintf(buf, sizeof(buf), "%ld job: %s\n", j->j_line->cl_id, j->j_line->cl_shell);
-               send(client->fcl_sock_fd, buf, len + 1, 0);
+       print_fields(fd, details ? 1 : all, details);
+       if ( details ) {
+           for ( j = queue_base; j != NULL; j = j->j_next ) {
+               if ( client->fcl_cmd[1] == j->j_line->cl_id ) {
+                   if (strcmp(client->fcl_user, j->j_line->cl_file->cf_user) == 0
+                       || is_root )
+                       print_line(fd, j->j_line, 1, 1);
+                   else
+                       send(fd, not_allowed_str, sizeof(not_allowed_str), 0);
+                   found = 1;
+                   break;
+               }
            }
        }
+       else
+           for ( j = queue_base; j != NULL; j = j->j_next ) {
+               if (all || strcmp(client->fcl_user, j->j_line->cl_file->cf_user) == 0 ) {
+                   print_line(fd, j->j_line, all, 0);
+                   found = 1;
+               }
+           }
+       if ( ! found )
+           send(fd, not_found_str, sizeof(not_found_str), 0);
        /* to tell fcrondyn there's no more data to wait */
-       send(client->fcl_sock_fd, END_STR, sizeof(END_STR), 0);
+       send(fd, END_STR, sizeof(END_STR), 0);
     }
     break;
-       
+    
     default:
-    {
-       
-       bzero(buf, sizeof(buf));
-       len = snprintf(buf, sizeof(buf), "From exe_cmd() : Hello %s !!\n",
-                      client->fcl_user);
-       debug("From exe_cmd() : Hello %s !!", client->fcl_user);
-       send(client->fcl_sock_fd, buf, len + 1, 0);
-       len = snprintf(buf, sizeof(buf), "How are you doing ?\n");
-       send(client->fcl_sock_fd, buf, len + 1, 0);
-       
+       send(fd, cmd_unknown_str, sizeof(cmd_unknown_str), 0);
+            
        /* to tell fcrondyn there's no more data to wait */
-       send(client->fcl_sock_fd, END_STR, sizeof(END_STR), 0);
-    }
+       send(fd, END_STR, sizeof(END_STR), 0);
     }
 }
 
+
 void
 check_socket(int num)
     /* check for new connection, command, connection closed */
@@ -252,7 +351,7 @@ check_socket(int num)
 
     client = fcrondyn_cl_base;
     while ( client != NULL ) {
-       if ( ! FD_ISSET(client->fcl_sock_fd, &read_set) || client->fcl_sock_fd==avoid_fd){
+       if (! FD_ISSET(client->fcl_sock_fd, &read_set) || client->fcl_sock_fd==avoid_fd){
            /* nothing to do on this one ... check the next one */
            prev_client = client;
            client = client->fcl_next;
@@ -269,7 +368,6 @@ check_socket(int num)
                    client = fcrondyn_cl_base = client->fcl_next;
                else {
                    prev_client->fcl_next = client->fcl_next;
-                   Flush(client->fcl_cmd);
                    Flush(client);
                    client = prev_client->fcl_next;
                }
@@ -289,6 +387,7 @@ check_socket(int num)
                auth_client(client);
            else {
                /* we've just read a command ... */
+               client->fcl_idle_since = now;
                exe_cmd(client);
            }
            prev_client = client;