/* * GProFTPD - A GTK+ frontend for the ProFTPD standalone server. * Copyright (C) 2001 - 2006 Magnus Loef (Magnus-swe) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. * */ #include #include #include #include #include #include #include #include "allocate.h" #include "chars_are_digits.h" /* This file will be created from nidump passwd / itll then be read * and removed (cant use /etc/passwd since its not kept current) */ #define GP_OSX_PASS_DUMP "/etc/gp_osx_passdump" int niutil_run_command(char *command) { /* Run a command */ FILE * fp; int i=0; if((fp=popen(command, "r"))==NULL) { printf("\nError running %s\n", command); } else { pclose(fp); i = 1; } return i; } int unlink_file(char *entity) { char *command; int unlink=0; if( ! file_exists(entity) ) { printf("Unlink: the file [%s] does not exist.\n", entity); unlink = 1; } else { command = allocate(8192); /* Remove the temporary file */ sprintf(command, "rm -f /etc/%s", entity); if( ! niutil_run_command(command) ) { printf("Error running: %s\n", command); free(command); exit (1); } free(command); unlink = 1; } return unlink; } int niutil_user_exists(G_CONST_RETURN gchar *username) { /* Checks if the system user exists */ FILE *fp; long conf_size; int x, user_exists=0; char tempname[4096]=""; char *check_buffer, *command; command = allocate(8192); sprintf(command, "/usr/bin/nidump passwd / > %s", GP_OSX_PASS_DUMP); if( ! niutil_run_command(command) ) { free(command); return user_exists; } free(command); /* Checks if the user exists in passwd */ if((fp=fopen(GP_OSX_PASS_DUMP,"r"))==NULL) { printf("Cannot open the nidump:ed passwd file.\n"); return user_exists; } else { fseek(fp, 0, SEEK_END); conf_size = ftell(fp); rewind(fp); check_buffer = allocate(conf_size); while(fgets(check_buffer, conf_size, fp)!=NULL) { for(x=0; check_buffer[x]; x++) { if(check_buffer[x]==':') { sprintf(tempname, check_buffer); tempname[x]='\0'; if( ! strcmp(username, tempname) ) { user_exists=1; break; } } if( check_buffer[x]=='\0' || check_buffer[x]=='\n' ) break; } if( user_exists ) break; } free(check_buffer); fclose(fp); } unlink_file(GP_OSX_PASS_DUMP); return user_exists; } int niutil_get_free_uid_above_500_() { FILE *fp; int i=0, begin=0, end=0, colon=0; long length, uid=0, num=0; char *command, *buffy, *tempuid, *gp_err=NULL; command = allocate(8192); sprintf(command, "/usr/bin/nidump passwd / > %s", GP_OSX_PASS_DUMP); if( ! niutil_run_command(command) ) { free(command); return uid; } free(command); if( ! file_exists(GP_OSX_PASS_DUMP) ) { printf("\nError: passwd file not found: %s\n", GP_OSX_PASS_DUMP); unlink_file(GP_OSX_PASS_DUMP); return uid; } /* Determine what gid is free and above 500 */ if((fp=fopen(GP_OSX_PASS_DUMP, "r"))==NULL) { unlink_file(GP_OSX_PASS_DUMP); return uid; } fseek(fp, 0, SEEK_END); length=ftell(fp); rewind(fp); buffy = allocate(length); tempuid = allocate(8192); while(fgets(buffy, length, fp)!=NULL) { /* Dont acctept bad input */ if( strlen(buffy) < 3 || strlen(buffy) > 1024 ) continue; colon=0; num=0; begin=0; end=0; /* Get the beginning of the gid */ for(i=0; buffy[i]!='\0'; i++) { if( buffy[i]==':' ) colon++; /* We have found the beginning of the uid */ if( colon==2 ) { begin=++i; break; } } /* Get the end of the uid */ for(i=i; buffy[i]!='\0'; i++) { end++; if( buffy[i]==':' ) { --end; /* strncpy(tempgid, &buffy[begin], end); grr */ sprintf(tempuid, &buffy[begin]); /* Terminate it after the last digit */ tempuid[end]='\0'; /* Collect the greatest uid */ if( chars_are_digits(tempuid) ) { /* Conversion to a valid long uid_t */ num = (uid_t) strtol(tempuid, &gp_err, 10); if( gp_err && *gp_err ) printf("Error Converting a valid long uid\n"); else if( num > uid ) uid=num; if(LONG_MIN==num) printf("LONG_MIN Conversion for uid\n"); if(LONG_MAX==num) printf("LONG_MAX Conversion for uid\n"); if(errno==ERANGE) printf("Conversion out of range for uid\n"); } /* No need to report a non digit or a negative value */ break; } } } free(buffy); free(tempuid); unlink_file(GP_OSX_PASS_DUMP); /* Add 1 to uid */ uid++; if( uid <= 499 ) return 500; else return uid; } int niutil_get_free_gid_above_500_() { /* FIXME USE uid_t and gid_t */ FILE *fp; int i=0, begin=0, end=0, colon=0; long length, gid=0, num=0; char *command, *buffy, *tempgid, *gp_err=NULL; command = allocate(8192); sprintf(command, "/usr/bin/nidump passwd / > %s", GP_OSX_PASS_DUMP); if( ! niutil_run_command(command) ) { free(command); return gid; } free(command); if( ! file_exists(GP_OSX_PASS_DUMP) ) { printf("\nError: passwd file not found: %s\n", GP_OSX_PASS_DUMP); return gid; } /* Determine what gid is free and above 500 */ if((fp=fopen(GP_OSX_PASS_DUMP, "r"))==NULL) { return gid; } fseek(fp, 0, SEEK_END); length=ftell(fp); rewind(fp); buffy = allocate(length); tempgid = allocate(8192); while(fgets(buffy, length, fp)!=NULL) { /* Dont acctept bad input */ if( strlen(buffy) < 3 || strlen(buffy) > 1024 ) continue; colon=0; num=0; begin=0; end=0; /* Get the beginning of the gid */ for(i=0; buffy[i]!='\0'; i++) { if( buffy[i]==':' ) colon++; /* We have found the beginning of the gid */ if( colon==3 ) { begin=++i; break; } } /* Get the end of the gid */ for(i=i; buffy[i]!='\0'; i++) { end++; if( buffy[i]==':' ) { --end; sprintf(tempgid, &buffy[begin]); /* Terminate it after the last digit */ tempgid[end]='\0'; /* Collect the greatest gid */ if( chars_are_digits(tempgid) ) { /* Conversion to a valid long gid_t */ num = (gid_t) strtol(tempgid, &gp_err, 10); if( gp_err && *gp_err ) printf("Error Converting a valid long gid \n"); else if( num > gid ) gid=num; if(LONG_MIN==num) printf("LONG_MIN Conversion error for gid\n"); if(LONG_MAX==num) printf("LONG_MAX Conversion error for gid\n"); if(errno==ERANGE) printf("Conversion out of range for gid\n"); } /* No need to report a non digit or a negative value */ break; } } } free(buffy); free(tempgid); unlink_file(GP_OSX_PASS_DUMP); /* Add 1 to gid */ gid++; if( gid <= 499 ) return 500; else return gid; } int niutil_useradd(G_CONST_RETURN gchar *username, G_CONST_RETURN gchar *shell) { char *command; long uid=0, gid=0, gp_id=0; command = allocate(8192); /* Create the new users database record */ sprintf(command, "/usr/bin/niutil -create / /users/%s", username); if( ! niutil_run_command(command) ) { printf("Error running: %s\n", command); free(command); exit (1); } /* Add a comment for this user */ sprintf(command, "/usr/bin/niutil -createprop / /users/%s realname %s", username, "ftp-user"); if( ! niutil_run_command(command) ) { printf("Error running: %s\n", command); free(command); exit (1); } if( ! (gid=niutil_get_free_gid_above_500_()) ) { printf("\nError: get_free_gid\n"); free(command); exit (1); } if( ! (uid=niutil_get_free_uid_above_500_()) ) { printf("\nError: get_free_uid\n"); free(command); exit (1); } /* We want uid's and gid's to be the same */ if( uid > gid ) gp_id = uid; else gp_id = gid; /* Set this users gid */ sprintf(command, "/usr/bin/niutil -createprop / /users/%s gid %li", username, gp_id); if( ! niutil_run_command(command) ) { printf("Error running: %s\n", command); free(command); exit (1); } /* Set this users uid */ sprintf(command, "/usr/bin/niutil -createprop / /users/%s uid %li", username, gp_id); if( ! niutil_run_command(command) ) { printf("Error running: %s\n", command); free(command); exit (1); } /* Set this users homedirectory to /dev/null */ sprintf(command, "/usr/bin/niutil -createprop / /users/%s home %s", username, "/dev/null"); if( ! niutil_run_command(command) ) { printf("Error running: %s\n", command); free(command); exit (1); } /* Set the name of the user */ sprintf(command, "/usr/bin/niutil -createprop / /users/%s name %s", username, username); if( ! niutil_run_command(command) ) { printf("Error running: %s\n", command); free(command); exit (1); } /* Set the users shell */ sprintf(command, "/usr/bin/niutil -createprop / /users/%s shell %s", username, shell); if( ! niutil_run_command(command) ) { printf("Error running: %s\n", command); free(command); exit (1); } /* /usr/bin/niutil -createprop . /users/username change changetime */ /* /usr/bin/niutil -createprop . /users/username expire expiretime */ free(command); /* Return true if the user exists */ return niutil_user_exists(username); } int niutil_userdel(G_CONST_RETURN gchar *username) { int i=0; char *command; /* Verify that the user really exists */ if( ! niutil_user_exists(username) ) return i; command = allocate(8192); sprintf(command, "/usr/bin/niutil -destroy / /users/%s", username); if( ! niutil_run_command(command) ) { printf("Error running: %s\n", command); } else i = 1; free(command); return i; } int niutil_password_user(G_CONST_RETURN gchar *username, G_CONST_RETURN gchar *password) { /* Password a user */ int i=0; char *command, *encrypted_pass; /* Verify that the user really exists */ if( ! niutil_user_exists(username) ) return i; /* Crypt return value should not be freed */ encrypted_pass = encrypt_password(password); if( encrypted_pass == NULL ) { printf("\nCrypt failed.\n"); exit (1); } command = allocate(8192); /* 'Encrypted Password' otherwise the shell might swallow it */ sprintf(command, "/usr/bin/niutil -createprop / /users/%s passwd '%s'", username, encrypted_pass); if( ! niutil_run_command(command) ) { printf("Error running: %s\n", command); free(command); exit (1); } else i = 1; free(command); return i; }