int main(int argc, char *argv[]) { FILE *tfp, *f; char user[MAX_STRING_LEN]; char realm[MAX_STRING_LEN]; char line[MAX_STRING_LEN]; char l[MAX_STRING_LEN]; char w[MAX_STRING_LEN]; char x[MAX_STRING_LEN]; char command[MAX_STRING_LEN]; int found; tn = NULL; signal(SIGINT, (void (*)(int)) interrupted); if (argc == 5) { if (strcmp(argv[1], "-c")) usage(); #ifdef NETWARE UnAugmentAsterisk(TRUE); SetCurrentNameSpace(NW_NS_LONG); SetTargetNameSpace(NW_NS_LONG); #endif if (!(tfp = fopen(argv[2], "w"))) { fprintf(stderr, "Could not open passwd file %s for writing.\n", argv[2]); perror("fopen"); exit(1); } printf("Adding password for %s in realm %s.\n", argv[4], argv[3]); add_password(argv[4], argv[3], tfp); fclose(tfp); exit(0); } else if (argc != 4) usage(); tn = tmpnam(NULL); if (!(tfp = fopen(tn, "w"))) { fprintf(stderr, "Could not open temp file.\n"); exit(1); } if (!(f = fopen(argv[1], "r"))) { fprintf(stderr, "Could not open passwd file %s for reading.\n", argv[1]); fprintf(stderr, "Use -c option to create new one.\n"); exit(1); } ap_cpystrn(user, argv[3], sizeof(user)); ap_cpystrn(realm, argv[2], sizeof(realm)); found = 0; while (!(getline(line, MAX_STRING_LEN, f))) { if (found || (line[0] == '#') || (!line[0])) { putline(tfp, line); continue; } strcpy(l, line); getword(w, l, ':'); getword(x, l, ':'); if (strcmp(user, w) || strcmp(realm, x)) { putline(tfp, line); continue; } else { printf("Changing password for user %s in realm %s\n", user, realm); add_password(user, realm, tfp); found = 1; } } if (!found) { printf("Adding user %s in realm %s\n", user, realm); add_password(user, realm, tfp); } fclose(f); fclose(tfp); #ifndef NETWARE #if defined(OS2) || defined(WIN32) sprintf(command, "copy \"%s\" \"%s\"", tn, argv[1]); #else sprintf(command, "cp %s %s", tn, argv[1]); #endif system(command); #else if (!(tfp = fopen(tn, "r"))) { fprintf(stderr, "Could not open temp file.\n"); exit(1); } if (!(f = fopen(argv[1], "w"))) { fprintf(stderr, "Could not open %s.\n", argv[1]); exit(1); } copy_file(f, tfp); #endif unlink(tn); return 0; }
/* * Let's do it. We end up doing a lot of file opening and closing, * but what do we care? This application isn't run constantly. */ int main(int argc, char *argv[]) { FILE *ftemp = NULL; FILE *fpw = NULL; char user[MAX_STRING_LEN]; char password[MAX_STRING_LEN]; char record[MAX_STRING_LEN]; char line[MAX_STRING_LEN]; char pwfilename[MAX_STRING_LEN]; char *arg; int found = 0; int alg = ALG_CRYPT; int newfile = 0; int nofile = 0; int noninteractive = 0; int i; int args_left = 2; tempfilename = NULL; signal(SIGINT, (void (*)(int)) interrupted); /* * Preliminary check to make sure they provided at least * three arguments, we'll do better argument checking as * we parse the command line. */ if (argc < 3) { return usage(); } /* * Go through the argument list and pick out any options. They * have to precede any other arguments. */ for (i = 1; i < argc; i++) { arg = argv[i]; if (*arg != '-') { break; } while (*++arg != '\0') { if (*arg == 'c') { newfile++; } else if (*arg == 'n') { nofile++; args_left--; } else if (*arg == 'm') { alg = ALG_APMD5; } else if (*arg == 's') { alg = ALG_APSHA; } else if (*arg == 'p') { alg = ALG_PLAIN; } else if (*arg == 'd') { alg = ALG_CRYPT; } else if (*arg == 'b') { noninteractive++; args_left++; } else { return usage(); } } } /* * Make sure we still have exactly the right number of arguments left * (the filename, the username, and possibly the password if -b was * specified). */ if ((argc - i) != args_left) { return usage(); } #ifdef NETWARE UnAugmentAsterisk(TRUE); SetCurrentNameSpace(NW_NS_LONG); SetTargetNameSpace(NW_NS_LONG); #endif if (newfile && nofile) { fprintf(stderr, "%s: -c and -n options conflict\n", argv[0]); return ERR_SYNTAX; } if (nofile) { i--; } else { if (strlen(argv[i]) > (sizeof(pwfilename) - 1)) { fprintf(stderr, "%s: filename too long\n", argv[0]); return ERR_OVERFLOW; } strcpy(pwfilename, argv[i]); if (strlen(argv[i + 1]) > (sizeof(user) - 1)) { fprintf(stderr, "%s: username too long (>%lu)\n", argv[0], (unsigned long)(sizeof(user) - 1)); return ERR_OVERFLOW; } } strcpy(user, argv[i + 1]); if ((arg = strchr(user, ':')) != NULL) { fprintf(stderr, "%s: username contains illegal character '%c'\n", argv[0], *arg); return ERR_BADUSER; } if (noninteractive) { if (strlen(argv[i + 2]) > (sizeof(password) - 1)) { fprintf(stderr, "%s: password too long (>%lu)\n", argv[0], (unsigned long)(sizeof(password) - 1)); return ERR_OVERFLOW; } strcpy(password, argv[i + 2]); } #ifdef WIN32 if (alg == ALG_CRYPT) { alg = ALG_APMD5; fprintf(stderr, "Automatically using MD5 format on Windows.\n"); } #elif defined(TPF) || defined(NETWARE) if (alg == ALG_CRYPT) { alg = ALG_APMD5; fprintf(stderr, "Automatically using MD5 format.\n"); } #endif #if (!(defined(WIN32) || defined(TPF) || defined(NETWARE))) if (alg == ALG_PLAIN) { fprintf(stderr,"Warning: storing passwords as plain text might " "just not work on this platform.\n"); } #endif if (! nofile) { /* * Only do the file checks if we're supposed to frob it. * * Verify that the file exists if -c was omitted. We give a special * message if it doesn't. */ if ((! newfile) && (! exists(pwfilename))) { fprintf(stderr, "%s: cannot modify file %s; use '-c' to create it\n", argv[0], pwfilename); perror("fopen"); exit(ERR_FILEPERM); } /* * Verify that we can read the existing file in the case of an update * to it (rather than creation of a new one). */ if ((! newfile) && (! readable(pwfilename))) { fprintf(stderr, "%s: cannot open file %s for read access\n", argv[0], pwfilename); perror("fopen"); exit(ERR_FILEPERM); } /* * Now check to see if we can preserve an existing file in case * of password verification errors on a -c operation. */ if (newfile && exists(pwfilename) && (! readable(pwfilename))) { fprintf(stderr, "%s: cannot open file %s for read access\n" "%s: existing auth data would be lost on " "password mismatch", argv[0], pwfilename, argv[0]); perror("fopen"); exit(ERR_FILEPERM); } /* * Now verify that the file is writable! */ if (! writable(pwfilename)) { fprintf(stderr, "%s: cannot open file %s for write access\n", argv[0], pwfilename); perror("fopen"); exit(ERR_FILEPERM); } } /* * All the file access checks (if any) have been made. Time to go to work; * try to create the record for the username in question. If that * fails, there's no need to waste any time on file manipulations. * Any error message text is returned in the record buffer, since * the mkrecord() routine doesn't have access to argv[]. */ i = mkrecord(user, record, sizeof(record) - 1, noninteractive ? password : NULL, alg); if (i != 0) { fprintf(stderr, "%s: %s\n", argv[0], record); exit(i); } if (nofile) { printf("%s\n", record); exit(0); } /* * We can access the files the right way, and we have a record * to add or update. Let's do it.. */ errno = 0; tempfilename = tmpnam(tname_buf); if ((tempfilename == NULL) || (*tempfilename == '\0')) { fprintf(stderr, "%s: unable to generate temporary filename\n", argv[0]); if (errno == 0) { errno = ENOENT; } perror("tmpnam"); exit(ERR_FILEPERM); } ftemp = fopen(tempfilename, "w+"); if (ftemp == NULL) { fprintf(stderr, "%s: unable to create temporary file '%s'\n", argv[0], tempfilename); perror("fopen"); exit(ERR_FILEPERM); } /* * If we're not creating a new file, copy records from the existing * one to the temporary file until we find the specified user. */ if (! newfile) { char scratch[MAX_STRING_LEN]; fpw = fopen(pwfilename, "r"); while (! (getline(line, sizeof(line), fpw))) { char *colon; if ((line[0] == '#') || (line[0] == '\0')) { putline(ftemp, line); continue; } strcpy(scratch, line); /* * See if this is our user. */ colon = strchr(scratch, ':'); if (colon != NULL) { *colon = '\0'; } if (strcmp(user, scratch) != 0) { putline(ftemp, line); continue; } found++; break; } } if (found) { fprintf(stderr, "Updating "); } else { fprintf(stderr, "Adding "); } fprintf(stderr, "password for user %s\n", user); /* * Now add the user record we created. */ putline(ftemp, record); /* * If we're updating an existing file, there may be additional * records beyond the one we're updating, so copy them. */ if (! newfile) { copy_file(ftemp, fpw); fclose(fpw); } /* * The temporary file now contains the information that should be * in the actual password file. Close the open files, re-open them * in the appropriate mode, and copy them file to the real one. */ fclose(ftemp); fpw = fopen(pwfilename, "w+"); ftemp = fopen(tempfilename, "r"); copy_file(fpw, ftemp); fclose(fpw); fclose(ftemp); unlink(tempfilename); return 0; }