/* This program read a file containing user accounts. the file is tabulated and contains 2 fields (for now). User id and name. It produces an ldif file usable to stuff in ldap. */ #include #include #include #include #include #include #include #include #include #include extern "C" int mkntpwd (const char *p, char lanman[33], char nt[33]); /* * i64c - convert an integer to a radix 64 character */ static int i64c(int i) { if (i < 0) return ('.'); else if (i > 63) return ('z'); if (i == 0) return ('.'); if (i == 1) return ('/'); if (i >= 2 && i <= 11) return ('0' - 2 + i); if (i >= 12 && i <= 37) return ('A' - 12 + i); if (i >= 38 && i <= 63) return ('a' - 38 + i); return ('\0'); } static void print64 (const char *var, const char *val) { char *name64 = base64_encode (val,strlen(val)); printf ("%s:: %s\n",var,name64); free (name64); } static const char *user2ldif_getitem( int fieldnum, const char *defval, const SSTRINGS &tb) { const char *ret = defval; if (fieldnum != -1){ SSTRING *s = tb.getitem(fieldnum); if (s != NULL) ret = s->get(); } return ret; } static int user2ldif_getitem( int fieldnum, int defval, const SSTRINGS &tb) { int ret = defval; if (fieldnum != -1){ SSTRING *s = tb.getitem(fieldnum); if (s != NULL) ret = s->getval(); } return ret; } int main (int argc, char *argv[]) { const char *dcs; char sep; int field_user; int field_name; int field_uid; int field_gid; int field_shell; int field_home; int field_password; int field_department; bool genpassword; bool smbinfo; int gid; const char *shell; const char *home; const char *user_prefix; // Prefix to place in front of the user // code. Sometime, the input only // contains numeric code so // we insert some prefix. const char *gid_prefix; // Prefix to insert in front of the gid FILE *flogpass; // File holding generated passwords int startuid; glocal.dcs = NULL; glocal.sep = '\t'; glocal.field_user = 0; glocal.field_name = 1; glocal.field_uid = -1; glocal.field_gid = -1; glocal.field_shell = -1; glocal.field_home = -1; glocal.field_password = -1; glocal.field_department = -1; glocal.genpassword = false; glocal.gid = 1; glocal.shell = "/bin/sh"; glocal.home = "/home"; glocal.user_prefix = ""; glocal.gid_prefix = NULL; glocal.flogpass = NULL; glocal.startuid = 1000; int ret = (argc, argv); extern const char *module_version; fprintf (stderr,"user2ldif version %s\n",module_version); fprintf (stderr,"\n" "Extract data from text file, one record per line\n" "and produce an LDIF file suitable for user account LDAP import\n" "\n" "Options:\n" "--dcdomain: DC sequence\n" "--home: Default base home directory\n" "\n" "--fieldsep C: Field separator. TAB is the default\n" "--field_user N: The field number holding the user id\n" "--field_name\n" "--field_shell\n" "--field_password\n" "--field_uid\n" "--field_gid\n" "--field_home\n" "--field_department\n" "\n" "--gid: Group number if the information is not found in the file\n" "--shell: Shell to use if not defined in the file\n" "--genpassword: Generate 6 characters passwords\n" "\tThis requires the path of a file to collect the generated\n" "\tpasswords.\n" "--userprefix XX: Prefix to insert in front of every user ID\n" "--gidprefix XX: Prefix to insert in front of every groud ID\n" "--startuid N: Allocate UID from this number, default 1000\n" "--smbinfo: generate ldap entries for samba\n" ); int ret = -1; if (strcmp(opt,"--dcdomain")==0){ glocal.dcs = val; ret = 1; }else if (strcmp(opt,"--fieldsep")==0){ glocal.sep = val[0]; ret = 1; }else if (strcmp(opt,"--field_user")==0){ glocal.field_user = atoi(val)-1; ret = 1; }else if (strcmp(opt,"--field_name")==0){ glocal.field_name = atoi(val)-1; ret = 1; }else if (strcmp(opt,"--field_uid")==0){ glocal.field_uid = atoi(val)-1; ret = 1; }else if (strcmp(opt,"--field_gid")==0){ glocal.field_gid = atoi(val)-1; ret = 1; }else if (strcmp(opt,"--field_shell")==0){ glocal.field_shell = atoi(val)-1; ret = 1; }else if (strcmp(opt,"--field_home")==0){ glocal.field_home = atoi(val)-1; ret = 1; }else if (strcmp(opt,"--field_password")==0){ glocal.field_password = atoi(val)-1; ret = 1; }else if (strcmp(opt,"--field_department")==0){ glocal.field_department = atoi(val)-1; ret = 1; }else if (strcmp(opt,"--gid")==0){ glocal.gid = atoi(val); ret = 1; }else if (strcmp(opt,"--shell")==0){ glocal.shell = val; ret = 1; }else if (strcmp(opt,"--home")==0){ glocal.home = val; ret = 1; }else if (strcmp(opt,"--userprefix")==0){ glocal.user_prefix = val; ret = 1; }else if (strcmp(opt,"--gidprefix")==0){ glocal.gid_prefix = val; ret = 1; }else if (strcmp(opt,"--genpassword")==0){ glocal.genpassword = true; glocal.flogpass = xconf_fopen (val,"a"); ret = 1; }else if (strcmp(opt,"--smbinfo")==0){ glocal.smbinfo = true; ret = 0; }else if (strcmp(opt,"--startuid")==0){ glocal.startuid = atoi(val); ret = 1; } return ret; int allocuid; FILE *frand; glocal.frand = NULL; if (glocal.genpassword){ glocal.frand = fopen ("/dev/urandom","r"); if (glocal.frand == NULL){ fprintf (stderr,"Can't open file /dev/urandom (%s)\n" ,strerror(errno)); exit (-1); } } if (glocal.dcs == NULL){ fprintf (stderr,"--dcdomain not specified\n"); exit (-1); } glocal.allocuid = glocal.startuid; int ret = (argv[0],true); SSTRINGS tb; int nb = str_splitline (line,glocal.sep,tb); if (nb < 2) return 0; const char *user = tb.getitem(glocal.field_user)->get(); SSTRING tmpuser; tmpuser.setfromf ("%s%s",glocal.user_prefix,user); user = tmpuser.get(); const char *name = tb.getitem(glocal.field_name)->get(); int uid = user2ldif_getitem(glocal.field_uid,-2,tb); if (uid == -2) uid = glocal.allocuid++; const char *gidstr = user2ldif_getitem (glocal.field_gid,(const char *)NULL,tb); SSTRING tmpgid; if (glocal.gid_prefix != NULL){ tmpgid.setfromf ("%s%s",glocal.gid_prefix,gidstr); gidstr = tmpgid.get(); } int gid = glocal.gid; if (gidstr != NULL){ if (isalpha(gidstr[0])){ struct group *g = getgrnam (gidstr); if (g != NULL) gid = g->gr_gid; }else{ gid = atoi(gidstr); } } const char *shell = user2ldif_getitem(glocal.field_shell,glocal.shell,tb); char tmphome[PATH_MAX]; sprintf (tmphome,"%s/%s",glocal.home,user); const char *home = user2ldif_getitem(glocal.field_home,tmphome,tb); const char *depart = user2ldif_getitem(glocal.field_department,(const char *)NULL,tb); if (getpwnam(user)!=NULL){ fprintf (stderr,"User %s exists\n",user); }else{ printf ("dn: uid=%s,%s\n",user,glocal.dcs); printf ("uid: %s\n",user); printf ("cn: %s\n",user); if (glocal.smbinfo) printf ("objectClass: sambaAccount\n"); printf ("objectClass: posixAccount\n"); printf ("objectClass: inetorgperson\n"); if (glocal.field_password != -1){ printf ("userPassword: %s\n",tb.getitem(glocal.field_password)->get()); }else if (glocal.genpassword){ char buf[6]; // We generate 6 character password composed of // one letter, one number, one letter, one number and so on // It should be hard to guess and hopefully possible // to remember char generate[7]; if (fread (buf,1,6,glocal.frand)==6){ for (int i=0; i<6; i++){ char carac; if (i & 1){ carac = (buf[i] % 10) + '0'; }else{ carac = (buf[i] % 26) + 'a'; } generate[i] = carac; } generate[6] = '\0'; } // New crypt using MD5 char salt[3+8+1]; { strcpy (salt,"$1$"); // Prefix for MD5 password unsigned char tmp[8]; fread(tmp,1,sizeof(tmp),glocal.frand); char *cp = salt+3; for (int i=0; i<8; i++) *cp++ = i64c(tmp[i] & 077); *cp = '\0'; } const char *store = crypt(generate,salt); printf ("userPassword: %s\n",store); if (glocal.smbinfo){ char lanman[33],ntpwd[33]; if (mkntpwd(generate,lanman,ntpwd)==0){ printf ("lmPassword: %s\n",lanman); printf ("ntPassword: %s\n",ntpwd); }else{ SSTRING cmd; cmd.setfromf ("/usr/local/sbin/mkntpwd %s",generate); (cmd.get(),10,true); const char *pt = strchr(line,':'); if (pt == NULL){ fprintf (stderr,"mkntpasswd ligne invalide: %s\n",line); }else{ SSTRING lm; lm.setfrom (line,(int)(pt-line)); printf ("lmPassword: %s\n",lm.get()); printf ("ntPassword: %s\n",pt+1); } return -1; fprintf (stderr,"mkntpwd: %s\n",line); return -1; } } if (glocal.flogpass != NULL){ fprintf (glocal.flogpass,"%s\t%s\n",user,generate); } } if (depart != NULL) printf ("departmentNumber: %s\n",depart); // printf ("shadowLastChange: 11441\n"); // printf ("shadowMax: 99999\n"); // printf ("shadowWarning: 7\n"); printf ("loginShell: %s\n",shell); printf ("uidNumber: %d\n",uid); printf ("gidNumber: %d\n",gid); if (glocal.smbinfo){ printf ("rid: %d\n",uid*2+1000); printf ("primaryGroupId: %d\n",uid*2+1001); } printf ("homeDirectory: %s\n",home); int lenname = strlen(name); { char tmp[strlen(name)+1]; strcpy (tmp,name); char *pt = strchr(tmp,' '); if (pt != NULL){ *pt++ = '\0'; print64 ("givenName",tmp); print64 ("sn",pt); pt[-1] = ' '; } } #if 1 char *name64 = base64_encode (name,lenname); printf ("gecos:: %s\n",name64); free (name64); #else char nameenc[strlen(name)+1]; char *ptn = nameenc; while (*name != '\0'){ if (*name >= 128){ *ptn = '-'; }else{ *ptn = *name; } name++; ptn++; } *ptn = '\0'; printf ("gecos: %s\n",nameenc); #endif printf ("\n"); } return 0; if (glocal.frand != NULL) fclose (glocal.frand); if (glocal.flogpass != NULL) fclose (glocal.flogpass); return ret; return ret; }