"Fossies" - the Fresh Open Source Software Archive

Member "jailkit-2.21/src/passwdparser.c" (4 Nov 2015, 5614 Bytes) of package /linux/privat/jailkit-2.21.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 "passwdparser.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.17_vs_2.18.

    1 /*
    2 Copyright (c) 2003, 2004, 2005, 2015 Olivier Sessink
    3 All rights reserved.
    4 
    5 Redistribution and use in source and binary forms, with or without
    6 modification, are permitted provided that the following conditions 
    7 are met:
    8   * Redistributions of source code must retain the above copyright 
    9     notice, this list of conditions and the following disclaimer.
   10   * Redistributions in binary form must reproduce the above 
   11     copyright notice, this list of conditions and the following 
   12     disclaimer in the documentation and/or other materials provided 
   13     with the distribution.
   14   * The names of its contributors may not be used to endorse or 
   15     promote products derived from this software without specific 
   16     prior written permission.
   17 
   18 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
   19 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
   20 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
   21 FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
   22 COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
   23 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
   24 BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
   25 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
   26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
   27 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
   28 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
   29 POSSIBILITY OF SUCH DAMAGE.
   30 
   31 */
   32 /* #define DEBUG */
   33 
   34 #include "config.h"
   35 #include <stdio.h>
   36 #include <sys/types.h>
   37 #include <pwd.h>
   38 #include <stdlib.h>
   39 #include <string.h> /* memset() */
   40 #include <strings.h> /* bzero() */
   41 #include <fcntl.h>
   42 #include "utils.h"
   43 
   44 #ifdef DEBUG
   45 #define DEBUG_MSG printf
   46 #else
   47 #define DEBUG_MSG(args...)
   48  /**/
   49 #endif
   50 
   51 
   52 static char *field_from_line(const char *line, int field) {
   53     int pos=0, fcount=0, fstart=0;
   54     while (1) {
   55         if (line[pos]==':') {
   56             if (field == fcount) { /* found the end of the field */
   57                 return strndup(line+fstart,pos-fstart);
   58             } else {
   59                 fcount++;
   60                 fstart = pos+1;
   61             }
   62         } else if (line[pos] == '\0') {
   63             if (fcount == field) return strndup(line+fstart,pos-fstart);
   64             return NULL;
   65         }
   66         pos ++;
   67     }
   68     return NULL; /* should not get to this line */
   69 }
   70 
   71 static int int_field_from_line(const char *line, int field) {
   72     char *tmp;
   73     int retval;
   74     tmp = field_from_line(line, field);
   75     if (tmp) {
   76         retval = atoi(tmp);
   77         free(tmp);
   78         return retval;
   79     }
   80     return -1;
   81 }
   82 
   83 #define BLOCKSIZE 1024
   84 static char * find_line(const char *filename, const char *fcont, int fnum) {
   85     FILE *fp;
   86     char buf[BLOCKSIZE+1];
   87     char *prev, *next, *retline=NULL;
   88     size_t num;
   89     int restlen=0;
   90     
   91 /*  printf("searching for %s in field %d\n",fcont,fnum);*/
   92     fp = fopen(filename,"r");
   93     if (fp == NULL) {
   94         return NULL;
   95     }
   96     /* set close-on-exec so this file descriptor will not be passed 
   97         to the a process after an exec() call */
   98     fcntl(fileno(fp), F_SETFD, FD_CLOEXEC);
   99     bzero(buf, (BLOCKSIZE+1)*sizeof(char));
  100     restlen = num = fread(buf, 1, BLOCKSIZE, fp);
  101     DEBUG_MSG("read %d bytes from %s\n",num,filename);
  102     prev = buf;
  103     while (num || restlen) {
  104         /* continue the loop if we either expect more bytes from the file (represented by num)
  105         or there are bytes in the block left (represented by restlen) */
  106         DEBUG_MSG("num=%d, restlen=%d, prev=%p\n",num,restlen,prev);
  107         next = strchr(prev, '\n');
  108         if (next || num==0) {
  109             char *field;
  110             if (next) *next = '\0';
  111             DEBUG_MSG("line: %s\n",prev);
  112             field = field_from_line(prev,fnum);
  113             DEBUG_MSG("field=%s, we are looking for %s\n",field,fcont);
  114             if (field && strcmp(field,fcont)==0) {
  115                 /* we found the line */
  116                 retline = strdup(prev);
  117 /*              printf("retline: %s\n",retline);*/
  118             }
  119             if (field) free(field);
  120             if (retline) {
  121                 DEBUG_MSG("found a line, returning %s\n",retline);
  122                 return retline;
  123             }
  124             if (next) {
  125                 *next = '\n';
  126                 prev = next+1;
  127             } else {
  128                 restlen = 0;
  129             }
  130         } else {
  131             restlen = restlen-(prev-buf);
  132             DEBUG_MSG("prev=%p,buf=%p,num=%d,restlen=%d\n",prev,buf,num,restlen);
  133             if (restlen > 0) {
  134                 /* no more newlines, move the  */
  135                 DEBUG_MSG("moving %d bytes to the beginning of the block\n",restlen);
  136                 memmove(buf, prev, restlen);
  137             } else {
  138                 DEBUG_MSG("*** can restlen be < 0 ????????? restlen=%d\n",restlen);
  139             }
  140             DEBUG_MSG("reading next block\n");
  141             num = fread(buf+restlen, 1, BLOCKSIZE-restlen, fp);
  142             DEBUG_MSG("read %d bytes from %s\n",num,filename);
  143             restlen += num;
  144             DEBUG_MSG("setting byte buf[%d] to \\0\n",restlen);
  145             buf[restlen] = '\0';
  146             prev = buf;
  147         }
  148     }
  149     DEBUG_MSG("returning NULL\n");
  150     return NULL;
  151 }
  152 
  153 struct passwd *internal_getpwuid(const char *filename, uid_t uid) {
  154     static struct passwd retpw;
  155     char find[11], *line;
  156     /* max unsigned int is 4294967295 which is 10 characters, and 11 for the \0 character */
  157     snprintf(find,11,"%u",(unsigned int)uid);
  158     line = find_line(filename, find, 2);
  159     if (line) {
  160         retpw.pw_name = field_from_line(line, 0);
  161         retpw.pw_gid = int_field_from_line(line, 3);
  162         retpw.pw_dir = field_from_line(line, 5);
  163         retpw.pw_shell = field_from_line(line, 6);
  164 
  165         if (retpw.pw_name == NULL || retpw.pw_gid == -1 || retpw.pw_shell == NULL || retpw.pw_dir == NULL
  166                 || strlen(retpw.pw_name)<1 || strlen(retpw.pw_dir)<1 || strlen(retpw.pw_shell)<1) {
  167             if (retpw.pw_name) free(retpw.pw_name);
  168             if (retpw.pw_dir) free(retpw.pw_dir);
  169             if (retpw.pw_shell) free(retpw.pw_shell);
  170             return NULL;
  171         }
  172 
  173         retpw.pw_uid = uid;
  174         retpw.pw_gecos = NULL; /* not required */
  175         retpw.pw_passwd = NULL; /* not required */      
  176         return &retpw;
  177     }
  178     return NULL;
  179 }
  180