123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- /*
- gopass.c -- Authorization password management.
- gopass [--cipher md5|blowfish] [--file filename] [--password password] realm user roles...
- This file provides facilities for creating passwords in a route configuration file.
- It supports either MD5 or Blowfish ciphers.
- */
- /********************************* Includes ***********************************/
- #include "goahead.h"
- /********************************** Locals ************************************/
- #define MAX_PASS 64
- /********************************* Forwards ***********************************/
- static char *getPassword(void);
- static void printUsage(void);
- static int writeAuthFile(char *path);
- #if ME_WIN_LIKE || VXWORKS
- static char *getpass(char *prompt);
- #endif
- /*********************************** Code *************************************/
- int main(int argc, char *argv[])
- {
- WebsBuf buf;
- char *cipher, *password, *authFile, *username, *encodedPassword, *realm, *cp, *roles;
- int i, errflg, nextArg;
- username = 0;
- errflg = 0;
- password = 0;
- authFile = 0;
- cipher = "blowfish";
- for (i = 1; i < argc && !errflg; i++) {
- if (argv[i][0] != '-') {
- break;
- }
- for (cp = &argv[i][1]; *cp && !errflg; cp++) {
- if (*cp == '-') {
- cp++;
- }
- if (smatch(cp, "cipher")) {
- if (++i == argc) {
- errflg++;
- } else {
- cipher = argv[i];
- if (!smatch(cipher, "md5") && !smatch(cipher, "blowfish")) {
- error("Unknown cipher \"%s\". Use \"md5\" or \"blowfish\".", cipher);
- }
- break;
- }
- } else if (smatch(cp, "file") || smatch(cp, "f")) {
- if (++i == argc) {
- errflg++;
- } else {
- authFile = argv[i];
- break;
- }
- } else if (smatch(cp, "password") || smatch(cp, "p")) {
- if (++i == argc) {
- errflg++;
- } else {
- password = argv[i];
- break;
- }
- } else {
- errflg++;
- }
- }
- }
- nextArg = i;
- if ((nextArg + 3) > argc) {
- errflg++;
- }
- if (errflg) {
- printUsage();
- exit(2);
- }
- realm = argv[nextArg++];
- username = argv[nextArg++];
- bufCreate(&buf, 0, 0);
- for (i = nextArg; i < argc; ) {
- bufPutStr(&buf, argv[i]);
- if (++i < argc) {
- bufPutc(&buf, ',');
- }
- }
- roles = sclone(buf.servp);
- logOpen();
- websOpenAuth(1);
-
- if (authFile && access(authFile, R_OK) == 0) {
- if (websLoad(authFile) < 0) {
- exit(2);
- }
- if (access(authFile, W_OK) < 0) {
- error("Cannot write to %s", authFile);
- exit(4);
- }
- }
- if (!password && (password = getPassword()) == 0) {
- exit(1);
- }
- encodedPassword = websMD5(sfmt("%s:%s:%s", username, realm, password));
- if (smatch(cipher, "md5")) {
- encodedPassword = websMD5(sfmt("%s:%s:%s", username, realm, password));
- } else {
- /* This uses the more secure blowfish cipher */
- encodedPassword = websMakePassword(sfmt("%s:%s:%s", username, realm, password), 16, 128);
- }
- if (authFile) {
- websRemoveUser(username);
- if (websAddUser(username, encodedPassword, roles) == 0) {
- exit(7);
- }
- if (writeAuthFile(authFile) < 0) {
- exit(6);
- }
- } else {
- printf("%s\n", encodedPassword);
- }
- websCloseAuth();
- return 0;
- }
- static int writeAuthFile(char *path)
- {
- FILE *fp;
- WebsKey *kp, *ap;
- WebsRole *role;
- WebsUser *user;
- WebsHash roles, users;
- char *tempFile;
- assert(path && *path);
- tempFile = websTempFile(NULL, "gp");
- if ((fp = fopen(tempFile, "w" FILE_TEXT)) == 0) {
- error("Cannot open %s", tempFile);
- return -1;
- }
- fprintf(fp, "#\n# %s - Authorization data\n#\n\n", basename(path));
- roles = websGetRoles();
- if (roles >= 0) {
- for (kp = hashFirst(roles); kp; kp = hashNext(roles, kp)) {
- role = kp->content.value.symbol;
- fprintf(fp, "role name=%s abilities=", kp->name.value.string);
- for (ap = hashFirst(role->abilities); ap; ap = hashNext(role->abilities, ap)) {
- fprintf(fp, "%s,", ap->name.value.string);
- }
- fputc('\n', fp);
- }
- fputc('\n', fp);
- }
- users = websGetUsers();
- if (users >= 0) {
- for (kp = hashFirst(users); kp; kp = hashNext(users, kp)) {
- user = kp->content.value.symbol;
- fprintf(fp, "user name=%s password=%s roles=%s", user->name, user->password, user->roles);
- fputc('\n', fp);
- }
- }
- fclose(fp);
- unlink(path);
- if (rename(tempFile, path) < 0) {
- error("Cannot create new %s from %s errno %d", path, tempFile, errno);
- return -1;
- }
- return 0;
- }
- static char *getPassword(void)
- {
- char *password, *confirm;
- password = getpass("New password: ");
- confirm = getpass("Confirm password: ");
- if (smatch(password, confirm)) {
- return password;
- }
- error("Password not verified");
- return 0;
- }
- #if WINCE
- static char *getpass(char *prompt)
- {
- return "NOT-SUPPORTED";
- }
- #elif ME_WIN_LIKE || VXWORKS
- static char *getpass(char *prompt)
- {
- static char password[MAX_PASS];
- int c, i;
- fputs(prompt, stdout);
- for (i = 0; i < (int) sizeof(password) - 1; i++) {
- #if VXWORKS
- c = getchar();
- #else
- c = _getch();
- #endif
- if (c == '\r' || c == EOF) {
- break;
- }
- if ((c == '\b' || c == 127) && i > 0) {
- password[--i] = '\0';
- fputs("\b \b", stdout);
- i--;
- } else if (c == 26) { /* Control Z */
- c = EOF;
- break;
- } else if (c == 3) { /* Control C */
- fputs("^C\n", stdout);
- exit(255);
- } else if (!iscntrl((uchar) c) && (i < (int) sizeof(password) - 1)) {
- password[i] = c;
- fputc('*', stdout);
- } else {
- fputc('', stdout);
- i--;
- }
- }
- if (c == EOF) {
- return "";
- }
- fputc('\n', stdout);
- password[i] = '\0';
- return sclone(password);
- }
- #endif /* ME_WIN_LIKE */
-
- /*
- Display the usage
- */
- static void printUsage(void)
- {
- error("usage: gopass [--cipher cipher] [--file path] [--password password] realm user roles...\n"
- "Options:\n"
- " --cipher md5|blowfish Select the encryption cipher. Defaults to md5\n"
- " --file filename Modify the password file\n"
- " --password password Use the specified password\n"
- "\n");
- }
- /*
- Copyright (c) Embedthis Software. All Rights Reserved.
- This software is distributed under commercial and open source licenses.
- You may use the Embedthis GoAhead open source license or you may acquire
- a commercial license from Embedthis Software. You agree to be fully bound
- by the terms of either license. Consult the LICENSE.md distributed with
- this software for full details and other copyrights.
- */
|