"Fossies" - the Fresh Open Source Software Archive

Member "ident2-v1.07_FINAL/common.c" (22 Jul 2005, 7080 Bytes) of package /linux/privat/old/ident2-v1.07_FINAL.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "common.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Ident-2 - an Identity server for UNIX
    3  * Copyright (C) 1998-2001 Michael Bacarella
    4  * Copyright (C) 2003 Netgraft Corporation
    5  *
    6  * This program is free software; you can redistribute it and/or
    7  * modify it under the terms of the GNU General Public License
    8  * as published by the Free Software Foundation; either version 2
    9  * of the License, or (at your option) any later version.
   10  *
   11  * This program is distributed in the hope that it will be useful,
   12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  * GNU General Public License for more details.
   15  *
   16  * You should have received a copy of the GNU General Public License
   17  * along with this program; if not, write to the Free Software
   18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   19  *
   20  * Please view the file README for program information.
   21  *
   22  *  Common function definitions.
   23  *  Used without regulation by other modules
   24  */
   25 
   26 #include "ident2.h"
   27 
   28 void *
   29 xmalloc (size_t nb)
   30 {
   31     void *p = malloc (nb);
   32     
   33     if (p == NULL) {
   34         fprintf (stderr, "ident2: terminating on memory allocation error\n");
   35         syslog (LOG_ERR, "error: memory allocation error");
   36         exit (1);
   37     }
   38     return p;
   39 }
   40 
   41     /*
   42      *  a (skewed) fgets() that works on file descriptors
   43      *  the '\r' charecter is ignored
   44      *  returns the number of bytes written into the given
   45      *   buffer, including the terminating NUL
   46      */
   47 static int
   48 _getl (int d, char *begin, u_short len)
   49 {
   50     char *p, *end;
   51 
   52     end = &begin[len-1]; /* leave room for terminating NUL */
   53     for (p = begin; p < end; ++p) {
   54         if (read (d, p, 1) != 1)
   55             break;
   56         if (*p == '\n')
   57             break;
   58         if (*p == '\r')
   59             p--;    /* ignore \r */
   60     }
   61     *p++ = 0;
   62     return p-begin;
   63 }
   64 
   65     /*
   66      *  this function is called directly as an inetd
   67      *  handler as well as a fork()ed into by the daemon
   68      *  service of the server..
   69      */
   70 void 
   71 child_service (int in, int out)
   72 {
   73     char buf[ID_BUF_SIZE];
   74 
   75     signal (SIGALRM, exit);
   76     alarm (Client_Timeout);
   77 
   78     if (m_reduce_rights () == -1)
   79         syslog (LOG_ERR, "error: cannot reduce self's rights "
   80             "[m_reduce_rights()]");
   81     else
   82         while (_getl (in, buf, ID_BUF_SIZE) != 0)
   83             nexus (out, buf);
   84 
   85     close (in);
   86     if (out != in)
   87         close (out);
   88 }
   89 
   90 
   91 typedef struct cl_t {
   92     int         sd;
   93     uid_t           uid;
   94     unsigned short      lp, rp;
   95     struct sockaddr_in  laddr, raddr;
   96     struct passwd       *pw;
   97 } cl_t;
   98 
   99     /*
  100      *      send an ident formatted reply to client
  101      */
  102 static void
  103 _clreply (cl_t *cl, char *rslt, char *info)
  104 {
  105     char buf[ID_BUF_SIZE+1];
  106 
  107     buf[ID_BUF_SIZE] = 0;
  108     
  109     snprintf (buf, ID_BUF_SIZE-1, "%d , %d : %s : %s\r\n",
  110         cl->lp, cl->rp, rslt, info);
  111     write (cl->sd, buf, strlen (buf));
  112 }
  113 
  114 
  115 static int
  116 _check_noident (cl_t *cl)
  117 {
  118     char p[ID_BUF_SIZE+1];
  119     
  120     p[ID_BUF_SIZE] = 0;
  121     
  122     snprintf (p, ID_BUF_SIZE-1, "%s/%s", cl->pw->pw_dir, NOIDENT_FILE);
  123     
  124     if (access (p, F_OK) == 0) {
  125         _clreply (cl, "ERROR", "HIDDEN-USER");
  126         syslog (LOG_INFO, "no reply to %s (query %d, %d) due to %s",
  127                 inet_ntoa (cl->raddr.sin_addr),
  128                 cl->lp, cl->rp, p);
  129         return 0;
  130     }
  131     return -1;
  132 }
  133 
  134 static int
  135 _check_user_ident (cl_t *cl)
  136 {
  137     FILE *fp;
  138     int retval = -1;
  139     char idfile[ID_BUF_SIZE+1];
  140     
  141     idfile[ID_BUF_SIZE] = 0;
  142     snprintf (idfile, ID_BUF_SIZE-1, "%s/%s",
  143         cl->pw->pw_dir, User_Ident_File);
  144     
  145     if (access (idfile, R_OK) == 0) {
  146         if ((fp = fopen (idfile, "r")) != NULL) {
  147             char *p, buf[4096];
  148             
  149             memset (buf, 0, 4096);  
  150             fgets (buf, 4095, fp);
  151             strtok (buf, "\r\n");
  152             
  153             if ((p = strstr (buf, "ident "))) {
  154                 char rply[ID_BUF_SIZE+1];
  155                 rply[ID_BUF_SIZE] = 0;
  156                 
  157                 snprintf (rply, ID_BUF_SIZE-1, "UNIX : %s", p+6);
  158                 _clreply (cl, "USERID", rply);
  159                 
  160                 syslog (LOG_INFO, "sent reply `%s' to query %s "
  161                     "(%d, %d), uid = %d", p,
  162                     inet_ntoa (cl->raddr.sin_addr),
  163                     cl->lp, cl->rp, cl->uid);
  164                 retval = 0;
  165             }
  166             fclose (fp);        
  167         }
  168     }
  169     return retval;
  170 }   
  171 
  172     /*
  173      * handy for users who use an ip masqueraded setup that just
  174      * want to friggin get on IRC and don't care what their ident
  175      * is. Or if you want to annoy your IRC admins, because they
  176      * totally deserve it.
  177      */
  178 static void
  179 _send_random_reply (cl_t *cl)
  180 {
  181     char randstr[RAND_STRING_LENGTH+1];
  182     char buf[ID_BUF_SIZE+1];
  183     size_t i;
  184 
  185     buf[ID_BUF_SIZE] = 0;
  186     
  187     srand (time(NULL));
  188     for (i = 0; i < RAND_STRING_LENGTH; i++) {
  189         randstr[i] = rand();
  190         while (randstr[i] > 'z')
  191             randstr[i] -= 26;
  192         while (randstr[i] < 'a')
  193             randstr[i] += 26;
  194     }
  195     randstr[RAND_STRING_LENGTH] = 0;
  196     
  197     snprintf (buf, ID_BUF_SIZE-1, "UNIX : %s", randstr);
  198 
  199     _clreply (cl, "USERID", buf);
  200     syslog (LOG_INFO, "sent random reply for query %s (%d, %d)",
  201         inet_ntoa (cl->raddr.sin_addr), cl->lp, cl->rp);
  202     
  203     return;
  204 }
  205     /*
  206      *  determines and collects client information
  207      *  and returns it in a neat and conveniant package
  208      */ 
  209 static cl_t *
  210 _new_cl (int sd, char *line)
  211 {
  212     int uid, ssiz = sizeof (struct sockaddr);
  213     cl_t *p, cl;
  214     char *s;
  215     
  216     cl.sd = sd;
  217     cl.lp = cl.rp = 0;
  218     
  219     if (!(s = strchr (line, ','))) {
  220         _clreply (&cl, "ERROR", "INVALID-PORT");
  221         return NULL;
  222     }       
  223     *s = 0;
  224     cl.lp = (u_short) atoi (line);
  225     cl.rp = (u_short) atoi (s+1);
  226 
  227     if (getsockname (sd, (struct sockaddr *)&cl.laddr, &ssiz) == -1) {
  228         syslog (LOG_WARNING, "warning: getsockname(): %s\n",
  229             strerror (errno));
  230                 _clreply (&cl, "ERROR", "UNKNOWN-ERROR");
  231                 return NULL;
  232     }
  233     if (getpeername (sd, (struct sockaddr *)&cl.raddr, &ssiz) == -1) {
  234         syslog (LOG_WARNING, "warning: getpeername(): %s\n",
  235             strerror (errno));
  236         _clreply (&cl, "ERROR", "UNKNOWN-ERROR");
  237         return NULL;
  238         }
  239 
  240     if (Reply_Always_Random == TRUE) {
  241         _send_random_reply (&cl);
  242         return NULL;
  243     }
  244 
  245     uid = m_get_uid (&cl.laddr.sin_addr, cl.lp, &cl.raddr.sin_addr, cl.rp);
  246     if (uid == -1) {
  247         syslog (LOG_WARNING, "warning: bad request: %d/%d, from %s",
  248             cl.lp, cl.rp, inet_ntoa (cl.raddr.sin_addr));
  249         _clreply (&cl, "ERROR", "NO-USER");
  250         return NULL;
  251     }
  252     cl.uid = uid;
  253         
  254     if ((cl.pw = getpwuid (cl.uid)) == NULL) {
  255         syslog (LOG_ERR, "warning: cannot map %d to a username: %s "
  256             "requested by query %s (%d, %d)", cl.uid,
  257                 strerror (errno), inet_ntoa (cl.raddr.sin_addr),
  258                 cl.lp, cl.rp);
  259         _clreply (&cl, "ERROR", "UNKNOWN-ERROR");
  260         return NULL;
  261     }
  262     p = xmalloc (sizeof (cl_t));
  263     *p = cl;
  264     
  265     return p;               
  266 }
  267 
  268     /**
  269      ** nexus
  270      **
  271      ** this is called by all service modes if
  272      ** any reply is to be returned to the
  273      ** client.
  274      **/
  275 void
  276 nexus (int sd, char *line)
  277 {
  278     cl_t *cl;
  279     char buf[ID_BUF_SIZE+1];
  280 
  281     buf[ID_BUF_SIZE] = 0;
  282     
  283     if ((cl = _new_cl (sd, line)) == NULL)
  284         return;
  285 
  286         /* if user configs are allowed, use the user's (if they
  287          * have one, else just use the global config */
  288     if (Allow_NOIDENT == TRUE)
  289         if (!_check_noident (cl)) {
  290             free (cl);
  291             return;
  292         }
  293         
  294     if (Use_User_Ident == TRUE)
  295         if (!_check_user_ident (cl)) {
  296             free (cl);
  297             return;
  298         }
  299     
  300     snprintf (buf, ID_BUF_SIZE-1, "UNIX : %s", cl->pw->pw_name);
  301     
  302     _clreply (cl, "USERID", buf);
  303     syslog (LOG_INFO, "sent reply `%s' to query %s "
  304             "(%d, %d), uid = %d", cl->pw->pw_name,
  305             inet_ntoa (cl->raddr.sin_addr), cl->lp,
  306             cl->rp, cl->uid);
  307 
  308     free (cl);
  309     return;     
  310 }
  311