"Fossies" - the Fresh Open Source Software Archive

Member "sarg-2.4.0/userinfo.c" (24 Dec 2019, 11745 Bytes) of package /linux/privat/sarg-2.4.0.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 "userinfo.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.3.11_vs_2.4.0.

    1 /*
    2  * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
    3  *                                                            1998, 2015
    4  *
    5  * SARG donations:
    6  *      please look at http://sarg.sourceforge.net/donations.php
    7  * Support:
    8  *     http://sourceforge.net/projects/sarg/forums/forum/363374
    9  * ---------------------------------------------------------------------
   10  *
   11  *  This program is free software; you can redistribute it and/or modify
   12  *  it under the terms of the GNU General Public License as published by
   13  *  the Free Software Foundation; either version 2 of the License, or
   14  *  (at your option) any later version.
   15  *
   16  *  This program is distributed in the hope that it will be useful,
   17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19  *  GNU General Public License for more details.
   20  *
   21  *  You should have received a copy of the GNU General Public License
   22  *  along with this program; if not, write to the Free Software
   23  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
   24  *
   25  */
   26 
   27 #include "include/conf.h"
   28 #include "include/defs.h"
   29 #include "include/stringbuffer.h"
   30 #include "include/alias.h"
   31 
   32 //! The number of users to group in one unit.
   33 #define USERS_PER_GROUP 50
   34 
   35 /*! \brief Group the users in one allocation unit.
   36 Structure to store a group of users and reduce the number of memory
   37 allocations.
   38 */
   39 struct usergroupstruct
   40 {
   41     //! The next group of users.
   42     struct usergroupstruct *next;
   43     //! A group of users.
   44     struct userinfostruct list[USERS_PER_GROUP];
   45     //! The number of users stored in the list.
   46     int nusers;
   47 };
   48 
   49 /*! \brief Hold pointer to scan through the user list.
   50 */
   51 struct userscanstruct
   52 {
   53     //! The group containing the user.
   54     struct usergroupstruct *group;
   55     //! The index of the user in the group.
   56     int index;
   57 };
   58 
   59 //! The first group of users.
   60 static struct usergroupstruct *first_user_group=NULL;
   61 //! The counter to generate unique user number when ::AnonymousOutputFiles is set.
   62 static int AnonymousCounter=0;
   63 //! String buffer to store the user's related constants.
   64 static StringBufferObject UserStrings=NULL;
   65 //! User aliases.
   66 static AliasObject UserAliases=NULL;
   67 
   68 extern struct ReadLogDataStruct ReadFilter;
   69 extern char StripUserSuffix[MAX_USER_LEN];
   70 extern int StripSuffixLen;
   71 extern char *userfile;
   72 
   73 struct userinfostruct *userinfo_create(const char *userid,const char *ip)
   74 {
   75     struct usergroupstruct *group, *last;
   76     struct userinfostruct *user;
   77     int i, j, lastuser;
   78     int skip;
   79     int flen;
   80     int count, clen;
   81     char cstr[9];
   82     char filename[MAX_USER_FNAME_LEN];
   83 
   84     if (!UserStrings) {
   85         UserStrings=StringBuffer_Create();
   86         if (!UserStrings) {
   87             debuga(__FILE__,__LINE__,_("Not enough memory to store the user's strings\n"));
   88             exit(EXIT_FAILURE);
   89         }
   90     }
   91 
   92     last=NULL;
   93     for (group=first_user_group ; group ; group=group->next) {
   94         if (group->nusers<USERS_PER_GROUP) break;
   95         last=group;
   96     }
   97 
   98     if (!group) {
   99         group=malloc(sizeof(*group));
  100         if (!group) {
  101             debuga(__FILE__,__LINE__,_("Not enough memory to store user \"%s\"\n"),userid);
  102             exit(EXIT_FAILURE);
  103         }
  104         memset(group,0,sizeof(*group));
  105         if (last)
  106             last->next=group;
  107         else
  108             first_user_group=group;
  109     }
  110     user=group->list+group->nusers++;
  111 
  112     user->id=StringBuffer_Store(UserStrings,userid);
  113     if (!user->id) {
  114         debuga(__FILE__,__LINE__,_("Not enough memory to store user ID \"%s\"\n"),userid);
  115         exit(EXIT_FAILURE);
  116     }
  117     user->label=user->id; //assign a label to avoid a NULL pointer in case none is provided
  118     if (ip) {
  119         /*
  120          * IP address is not the same as the user's ID. A separate buffer
  121          * must be allocated.
  122          */
  123         user->id_is_ip=false;
  124         user->ip=StringBuffer_Store(UserStrings,ip);
  125     } else {
  126         /*
  127          * User's IP address share the same buffer as the user's ID.
  128          */
  129         user->id_is_ip=true;
  130         user->ip=user->id;
  131     }
  132 
  133     if (AnonymousOutputFiles) {
  134         snprintf(filename,sizeof(filename),"%d",AnonymousCounter++);
  135     } else {
  136         skip=0;
  137         j=0;
  138         for (i=0 ; userid[i] && j<MAX_USER_FNAME_LEN-1 ; i++) {
  139             if (isalnum(userid[i]) || userid[i]=='-' || userid[i]=='_') {
  140                 filename[j++]=userid[i];
  141                 skip=0;
  142             } else {
  143                 if (!skip) {
  144                     filename[j++]='_';
  145                     skip=1;
  146                 }
  147             }
  148         }
  149         if (j==0) filename[j++]='_'; //don't leave a file name empty
  150         flen=j;
  151         filename[j]='\0';
  152 
  153         count=0;
  154         for (group=first_user_group ; group ; group=group->next) {
  155             lastuser=(group->next) ? group->nusers : group->nusers-1;
  156             for (i=0 ; i<lastuser ; i++) {
  157                 if (strcasecmp(filename,group->list[i].filename)==0) {
  158                     clen=sprintf(cstr,"+%X",count++);
  159                     if (flen+clen<MAX_USER_FNAME_LEN)
  160                         strcpy(filename+flen,cstr);
  161                     else
  162                         strcpy(filename+MAX_USER_FNAME_LEN-clen,cstr);
  163                 }
  164             }
  165         }
  166     }
  167     user->filename=StringBuffer_Store(UserStrings,filename);
  168     if (!user->filename)
  169     {
  170         debuga(__FILE__,__LINE__,_("Not enough memory to store the file name for user \"%s\"\n"),user->id);
  171         exit(EXIT_FAILURE);
  172     }
  173 
  174     return(user);
  175 }
  176 
  177 void userinfo_free(void)
  178 {
  179     struct usergroupstruct *group, *next;
  180 
  181     for (group=first_user_group ; group ; group=next) {
  182         next=group->next;
  183         free(group);
  184     }
  185     first_user_group=NULL;
  186     StringBuffer_Destroy(&UserStrings);
  187 }
  188 
  189 /*!
  190  * Store the user's label.
  191  * \param uinfo The user info structure created by userinfo_create().
  192  * \param label The string label to store.
  193  */
  194 void userinfo_label(struct userinfostruct *uinfo,const char *label)
  195 {
  196     if (!uinfo) return;
  197     if (!UserStrings) return;
  198     uinfo->label=StringBuffer_Store(UserStrings,label);
  199     if (!uinfo->label) {
  200         debuga(__FILE__,__LINE__,_("Not enough memory to store label \"%s\" of user \"%s\"\n"),label,uinfo->id);
  201         exit(EXIT_FAILURE);
  202     }
  203 }
  204 
  205 struct userinfostruct *userinfo_find_from_file(const char *filename)
  206 {
  207     struct usergroupstruct *group;
  208     int i;
  209 
  210     for (group=first_user_group ; group ; group=group->next) {
  211         for (i=0 ; i<group->nusers ; i++)
  212             if (strcmp(filename,group->list[i].filename)==0)
  213                 return(group->list+i);
  214     }
  215     return(NULL);
  216 }
  217 
  218 struct userinfostruct *userinfo_find_from_id(const char *id)
  219 {
  220     struct usergroupstruct *group;
  221     int i;
  222 
  223     for (group=first_user_group ; group ; group=group->next) {
  224         for (i=0 ; i<group->nusers ; i++)
  225             if (strcmp(id,group->list[i].id)==0)
  226                 return(group->list+i);
  227     }
  228     return(NULL);
  229 }
  230 
  231 struct userinfostruct *userinfo_find_from_ip(const char *ip)
  232 {
  233     struct usergroupstruct *group;
  234     int i;
  235 
  236     for (group=first_user_group ; group ; group=group->next) {
  237         for (i=0 ; i<group->nusers ; i++)
  238             if (strcmp(ip,group->list[i].ip)==0)
  239                 return(group->list+i);
  240     }
  241     return(NULL);
  242 }
  243 
  244 /*!
  245 Start the scanning of the user list.
  246 
  247 \return The object to pass to subsequent scanning functions or NULL
  248 if it failed. The object must be freed with a call to userinfo_stop().
  249 */
  250 userscan userinfo_startscan(void)
  251 {
  252     userscan uscan;
  253 
  254     uscan=malloc(sizeof(*uscan));
  255     if (!uscan) return(NULL);
  256     uscan->group=first_user_group;
  257     uscan->index=0;
  258     return(uscan);
  259 }
  260 
  261 /*!
  262 Free the memory allocated by userinfo_start().
  263 
  264 \param uscan The object created by userinfo_start().
  265 */
  266 void userinfo_stopscan(userscan uscan)
  267 {
  268     free(uscan);
  269 }
  270 
  271 /*!
  272 Get the user pointed to by the object and advance the object
  273 to the next user.
  274 
  275 \param uscan The object created by userinfo_start().
  276 
  277 \return The user in the list or NULL if the end of the list
  278 is reached.
  279 */
  280 struct userinfostruct *userinfo_advancescan(userscan uscan)
  281 {
  282     struct userinfostruct *uinfo;
  283 
  284     if (!uscan) return(NULL);
  285     if (!uscan->group) return(NULL);
  286     if (uscan->index<0 || uscan->index>=uscan->group->nusers) return(NULL);
  287 
  288     uinfo=uscan->group->list+uscan->index;
  289 
  290     ++uscan->index;
  291     if (uscan->index>=uscan->group->nusers) {
  292         uscan->group=uscan->group->next;
  293         uscan->index=0;
  294     }
  295     return(uinfo);
  296 }
  297 
  298 /*!
  299 Clear the general purpose flag from all the user's info.
  300 */
  301 void userinfo_clearflag(void)
  302 {
  303     struct usergroupstruct *group;
  304     int i;
  305 
  306     for (group=first_user_group ; group ; group=group->next) {
  307         for (i=0 ; i<group->nusers ; i++)
  308             group->list[i].flag=0;
  309     }
  310 }
  311 
  312 /*!
  313 Read the file containing the user names to alias in the report.
  314 
  315 \param Filename The name of the file.
  316 */
  317 void read_useralias(const char *Filename)
  318 {
  319     FileObject *fi;
  320     longline line;
  321     char *buf;
  322 
  323     if (debug) debuga(__FILE__,__LINE__,_("Reading user alias file \"%s\"\n"),Filename);
  324 
  325     UserAliases=Alias_Create();
  326     if (!UserAliases) {
  327         debuga(__FILE__,__LINE__,_("Cannot store user's aliases\n"));
  328         exit(EXIT_FAILURE);
  329     }
  330 
  331     fi=FileObject_Open(Filename);
  332     if (!fi) {
  333         debuga(__FILE__,__LINE__,_("Cannot read user name alias file \"%s\": %s\n"),Filename,FileObject_GetLastOpenError());
  334         exit(EXIT_FAILURE);
  335     }
  336 
  337     if ((line=longline_create())==NULL) {
  338         debuga(__FILE__,__LINE__,_("Not enough memory to read file \"%s\"\n"),Filename);
  339         exit(EXIT_FAILURE);
  340     }
  341 
  342     while ((buf=longline_read(fi,line)) != NULL) {
  343         if (Alias_Store(UserAliases,buf)<0) {
  344             debuga(__FILE__,__LINE__,_("While reading \"%s\"\n"),Filename);
  345             exit(EXIT_FAILURE);
  346         }
  347     }
  348 
  349     longline_destroy(&line);
  350     if (FileObject_Close(fi)) {
  351         debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),Filename,FileObject_GetLastCloseError());
  352         exit(EXIT_FAILURE);
  353     }
  354 
  355     if (debug) {
  356         debuga(__FILE__,__LINE__,_("List of user names to alias:\n"));
  357         Alias_PrintList(UserAliases);
  358     }
  359 }
  360 
  361 /*!
  362 Free the memory allocated by read_useralias().
  363 */
  364 void free_useralias(void)
  365 {
  366     Alias_Destroy(&UserAliases);
  367 }
  368 
  369 /*!
  370 Replace the user's name or ID by an alias if one is defined.
  371 
  372 \param user The user's name or ID as extracted from the report.
  373 
  374 \retval USERERR_NoError No error.
  375 \retval USERERR_NameTooLong User name too long.
  376 */
  377 enum UserProcessError process_user(const char **UserPtr,const char *IpAddress,bool *IsIp)
  378 {
  379     const char *user=*UserPtr;
  380     static char UserBuffer[MAX_USER_LEN];
  381     const char *auser;
  382 
  383     if (UserIp) {
  384         user=IpAddress;
  385         *IsIp=true;
  386     } else {
  387         *IsIp=false;
  388 
  389         if (StripSuffixLen>0)
  390         {
  391             int x=strlen(user);
  392             if (x>StripSuffixLen && strcasecmp(user+(x-StripSuffixLen),StripUserSuffix)==0)
  393             {
  394                 if (x-StripSuffixLen>=sizeof(UserBuffer))
  395                     return(USERERR_NameTooLong);
  396                 safe_strcpy(UserBuffer,user,x-StripSuffixLen+1);
  397                 user=UserBuffer;
  398             }
  399         }
  400         if (strlen(user)>MAX_USER_LEN)
  401             return(USERERR_NameTooLong);
  402 
  403         if (testvaliduserchar(user))
  404             return(USERERR_InvalidChar);
  405 
  406         if ((user[0]=='\0') || (user[1]=='\0' && (user[0]=='-' || user[0]==' '))) {
  407             if (RecordsWithoutUser == RECORDWITHOUTUSER_IP) {
  408                 user=IpAddress;
  409                 *IsIp=true;
  410             }
  411             if (RecordsWithoutUser == RECORDWITHOUTUSER_IGNORE)
  412                 return(USERERR_EmptyUser);
  413             if (RecordsWithoutUser == RECORDWITHOUTUSER_EVERYBODY)
  414                 user="everybody";
  415         } else {
  416             if (NtlmUserFormat == NTLMUSERFORMAT_USER) {
  417                 const char *str;
  418                 if ((str=strchr(user,'+'))!=NULL || (str=strchr(user,'\\'))!=NULL || (str=strchr(user,'_'))!=NULL) {
  419                     user=str+1;
  420                 }
  421             }
  422         }
  423     }
  424 
  425     if (us[0]!='\0' && strcmp(user,us)!=0)
  426         return(USERERR_Untracked);
  427 
  428     if (ReadFilter.SysUsers) {
  429         char wuser[MAX_USER_LEN+2]=":";
  430 
  431         strcat(wuser,user);
  432         strcat(wuser,":");
  433         if (strstr(userfile, wuser) == 0)
  434             return(USERERR_SysUser);
  435     }
  436 
  437     if (ReadFilter.UserFilter) {
  438         if (!vuexclude(user)) {
  439             if (debugz>=LogLevel_Process) debuga(__FILE__,__LINE__,_("Excluded user: %s\n"),user);
  440             return(USERERR_Ignored);
  441         }
  442     }
  443 
  444     auser=Alias_Replace(UserAliases,user);
  445     if (auser!=user) {
  446         if (*auser==ALIAS_PREFIX) auser++;//no need for that indicator for a user name
  447         user=auser;
  448         *IsIp=false;
  449     }
  450 
  451     // include_users
  452     if (IncludeUsers[0] != '\0') {
  453         char wuser[MAX_USER_LEN+2]=":";
  454         char *str;
  455 
  456         strcat(wuser,user);
  457         strcat(wuser,":");
  458         str=strstr(IncludeUsers,wuser);
  459         if (!str)
  460             return(USERERR_Excluded);
  461     }
  462 
  463     if (user[0]=='\0' || (user[1]=='\0' && (user[0]=='-' || user[0]==' ' || user[0]==':')))
  464         return(USERERR_EmptyUser);
  465 
  466     *UserPtr=user;
  467     return(USERERR_NoError);
  468 }