/* users.c -- eurephiadm command - User Account Management * * GPLv2 only - Copyright (C) 2008, 2009 * David Sommerseth * * 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; version 2 * of the License. * * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * */ #include #include #include #include #include #ifdef HAVE_LIBXML2 #include #include #endif #define MODULE "eurephia::Users" #include #include #include #include #include #include #include #include #include #include #include "../argparser.h" #include "../get_console_input.h" #include "../field_print.h" #include "../parse_certificate_files.h" #include "../xsltparser.h" // Reuse code which is in certificats.c #define SHOWCERTS_FIREWALL 0x001 #define SHOWCERTS_DIGEST 0x002 void xmlPrint_certs(xmlXPathContext *certsXP, const char *xpath, int show_flags); int register_certificate(eurephiaCTX *ctx, int depth, const char *digest, const char *cname, const char *org, const char *email); void display_users_help(int page) { printf("\n%s -- Administer user accounts\n\n", MODULE); switch( page ) { case 'l': printf("The list mode can accept one parameter:\n\n" " -S | --sort Decide the sort order of the user list\n" "\n" "Available sort keys are: uid, username, activated, deactivated and lastaccess\n\n"); break; case 's': printf("The show mode shows more information about a user account.\n" "One of the following arguments are required:\n\n" " -i | --uid Numeric user ID\n" " -u | --username User name\n" "\n" "Optional arguments are:\n\n" " -l | --lastlog Show users lastlog entries\n" " -L | --lastlog-details Show a more verbose lastlog\n" " -a | --attempts Show users failed attempts and blaclisting\n" " -b | --blacklist Alias for --attempts\n" "\n"); break; case 'a': printf("The activate mode activates an account which not activated or deactivated.\n" "One of the following arguments are required:\n\n" " -i | --uid Numeric user ID\n" " -u | --username User name\n\n"); break; case 'd': printf("The deactivate mode deactivates a user account.\n" "One of the following arguments are required:\n\n" " -i | --uid Numeric user ID\n" " -u | --username User name\n\n"); break; case 'A': printf("The add user mode registers a new user account.\n" "Both of the following arguments are required:\n\n" " -u | --username User name to use for the new account (required)\n" " -P | --password Assign a new password via the command line.\n\n" "(not implemented yet) To register this new account against a certificate\n" "you can use the following arguments. These arguments cannot be used together.\n\n" " -C | --certid Use already registered certificate, identified by certid.\n" " -D | --digest Use already registered certificate, identified by digest.\n" " -c | --certfile Use the given certificate file and register it along with\n" " the account.\n" " -2 | --pkcs12 Certificate file is using the PKCS#12 format.\n\n"); break; case 'D': printf("The delete user mode will delete a user account from the database.\n" "One of the following arguments are required:\n\n" " -i | --uid Numeric user ID\n" " -u | --username User name\n\n"); break; case 'p': printf("The change password mode is used for changing password for other\n" "persons than yourself.\n\n" "One of the following arguments are required:\n\n" " -i | --uid Numeric user ID\n" " -u | --username User name\n\n"); break; default: printf("Available modes:\n" " -l | --list List all user accounts\n" " -s | --show Show user account details\n" " -a | --activate Activate a user account\n" " -d | --deactivate Deactivate a user account\n" " -A | --add Add a new user account\n" " -D | --delete Delete a user account\n" " -p | --password Change password on a users account\n" " -h | --help Further help for these modes\n\n"); break; } } int help_Users2(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { e_options helpargs[] = { {"--list", "-l", 0}, {"--show", "-s", 0}, {"--activate", "-a", 0}, {"--deactivate", "-d", 0}, {"--add", "-A", 0}, {"--delete", "-D", 0}, {"--password", "-p", 0}, {NULL, NULL, 0} }; int i = 1; display_users_help(eurephia_getopt(&i, argc, argv, helpargs)); return 0; } void help_Users() { display_users_help(0); } int list_users(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { xmlDoc *userlist = NULL; xmlNode *users_n = NULL; int i = 0; char *sortkeys = NULL; e_options listargs[] = { {"--sort", "-S", 1}, {"--help", "-h", 0}, {NULL, NULL, 0} }; assert((ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL)); // Parse arguments for( i = 1; i < argc; i++ ) { switch( eurephia_getopt(&i, argc, argv, listargs) ) { case 'S': sortkeys = optargs[0]; i++; break; case 'h': display_users_help('l'); return 0; default: return 1; } } // Retrieve the user list - as an XML document userlist = eDBadminGetUserList(ctx, sortkeys); if( userlist == NULL ) { fprintf(stderr, "Error retrieving user list\n"); return 1; } fprintf(stdout, " %3s %-20.32s %-16.16s %-16.16s %-16.16s\n", "ID", "Username", "Activated","Deactivated","Last access"); fprintf(stdout, " ----------------------------------------------------------------------------\n"); // Find the user list node in the XML doc users_n = eurephiaXML_getRoot(ctx, userlist, "userlist", 1); if( users_n == NULL ) { fprintf(stderr, "Could not retrieve valid data\n"); xmlFreeDoc(userlist); return 1; } users_n = users_n->children; // Loop through the user list for( ; users_n != NULL; users_n = users_n->next ) { fprintf(stdout, " %3.3s %-20.32s %-16.16s %-16.16s %-16.16s\n", xmlGetAttrValue(users_n->properties, "uid"), xmlGetNodeContent(users_n, "username"), defaultValue(xmlGetNodeContent(users_n, "activated"), "(Not activated)"), defaultValue(xmlGetNodeContent(users_n, "deactivated"), "-"), defaultValue(xmlGetNodeContent(users_n, "last_accessed"), "-")); } fprintf(stdout, " ----------------------------------------------------------------------------\n"); xmlFreeDoc(userlist); return 0; } char *xmlFlags2str(xmlXPathContext *xpathCTX, const char *xpath) { xmlXPathObject *flagsObj = NULL; int i = 0; static char flagstr[8194]; memset(&flagstr, 0, 8194); // Find the flag nodes given in the XPath query flagsObj = xmlXPathEvalExpression((xmlChar *)xpath, xpathCTX); if( flagsObj == NULL ) { fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", xpath); return flagstr; } // Loop through all nodes and build up a string of all flags for( i = 0; i < flagsObj->nodesetval->nodeNr; i++ ) { char *flag = xmlExtractContent(flagsObj->nodesetval->nodeTab[i]); if( flag != NULL ) { strncat(flagstr, flag, 8191-strlen_nullsafe(flagstr)); strcat(flagstr, " "); } } xmlXPathFreeObject(flagsObj); return flagstr; } // Show account information for a particular user int show_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { xmlXPathContext *user_XP = NULL; int i, crit_set = 0, lastlog_verb = 0; long int show_info = USERINFO_user | USERINFO_certs; xmlDoc *user_xml = NULL, *srch_xml = NULL; xmlNode *srch_root = NULL, *user_n = NULL; e_options activargs[] = { {"--uid", "-i", 1}, {"--username", "-u", 1}, {"--lastlog", "-l", 0}, {"--lastlog-details", "-L", 0}, {"--attempts", "-a", 0}, {"--blacklist", "-b", 0}, // Alias for -a | --attempts {"--help", "-h", 0}, {NULL, NULL, 0} }; assert((ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL)); // Create a fieldMapping XML document, used for searching the user database eurephiaXML_CreateDoc(ctx, 1, "fieldMapping", &srch_xml, &srch_root); xmlNewProp(srch_root, (xmlChar *) "table", (xmlChar *)"users"); // Which table to search in // Argument parsing crit_set = 0; for( i = 1; i < argc; i++ ) { switch( eurephia_getopt(&i, argc, argv, activargs) ) { case 'i': if( atoi_nullsafe(optargs[0]) == 0 ) { fprintf(stderr, "%s: Invalid user id\n", MODULE); return 1; } xmlNewChild(srch_root, NULL, (xmlChar *)"uid", (xmlChar *) optargs[0]); crit_set++; break; case 'u': if( strlen_nullsafe(optargs[0]) < 3 ) { fprintf(stderr, "%s: User name too short\n", MODULE); return 1; } xmlNewChild(srch_root, NULL, (xmlChar *)"username", (xmlChar *)optargs[0]); crit_set++; break; case 'a': case 'b': show_info = USERINFO_attempts | USERINFO_blacklist; break; case 'L': lastlog_verb = 1; case 'l': show_info = USERINFO_lastlog; break; case 'h': display_users_help('s'); return 0; default: return 1; } } // Check if we have the needed search criterias if( crit_set == 0 ) { fprintf(stderr, "%s: Missing required parameter. You must provide either user id or user name\n", MODULE); xmlFreeDoc(srch_xml); return 1; } if( crit_set > 1 ) { fprintf(stderr, "%s: You cannot have several search criterias (-i | -u)\n", MODULE); xmlFreeDoc(srch_xml); return 1; } // Search and find the user which was requested if( (user_xml = eDBadminGetUserInfo(ctx, show_info, srch_xml)) == NULL ) { fprintf(stderr, "%s: User not found\n", MODULE); return 1; } xmlFreeDoc(srch_xml); user_n = eurephiaXML_getRoot(ctx, user_xml, "user", 1); if( user_n == NULL ) { fprintf(stderr, "Could not retrieve valid data\n"); xmlFreeDoc(user_xml); return 1; } // Create a XPath context for functions which users XPath to locate info user_XP = xmlXPathNewContext(user_xml); if( user_XP == NULL ) { fprintf(stderr,"Error: unable to create new XPath context\n"); return 1; } if( show_info & USERINFO_user ) { xmlNode *lastacc = NULL; lastacc = xmlFindNode(user_n, "last_accessed"); field_print_str("User id", xmlGetAttrValue(user_n->properties, "uid")); field_print_str("User name", xmlGetNodeContent(user_n, "username")); field_print_str("Login count", xmlGetAttrValue(lastacc->properties, "logincount")); field_print_str("Last accessed", xmlExtractContent(lastacc)); field_print_str("Activated", xmlGetNodeContent(user_n, "activated")); field_print_str("Dectivated", xmlGetNodeContent(user_n, "deactivated")); field_print_str("Flags", xmlFlags2str(user_XP, "/eurephia/user/flags/flag")); printf("\n"); } // Show associated certificates if we was asked to show this info if( show_info & USERINFO_certs ) { xmlPrint_certs(user_XP, "/eurephia/user/certificates/certificate", SHOWCERTS_FIREWALL); } if( show_info & USERINFO_lastlog ) { #ifdef FIREWALL char *xsltparams[] = {"view", "'list'", "firewall", "'1'", NULL}; #else char *xsltparams[] = {"view", "'list'", "firewall", "'0'", NULL}; #endif if( lastlog_verb ) { xsltparams[1] = "'details'"; } printf("** Lastlog entries for %s\n\n", xmlGetNodeContent(user_n, "username")); xslt_print_xmldoc(stdout, cfg, user_xml, "lastlog.xsl", (const char **)xsltparams); } if( (show_info & USERINFO_attempts) || (show_info & USERINFO_blacklist) ) { xmlNode *atmpt = NULL, *blackl = NULL; atmpt = xmlFindNode(user_n, "attempts"); blackl = xmlFindNode(user_n, "blacklist"); if( atmpt->children != NULL ) { field_print_str("Login attempt information",""); field_print_str("Failed attempts", xmlGetAttrValue(atmpt->properties, "attempts")); field_print_str("First attempt", xmlGetNodeContent(atmpt, "first_attempt")); field_print_str("Last attempt", xmlGetNodeContent(atmpt, "last_attempt")); } else { field_print_str("Login attempt information","Nothing registered"); } printf("\n"); if( blackl->children != NULL) { field_print_str("Blacklist information",""); field_print_str("Blacklisted", xmlGetNodeContent(blackl, "blacklisted")); field_print_str("Last attempt", xmlGetNodeContent(blackl, "last_accessed")); } else { field_print_str("Blacklist information","Nothing registered"); } printf("\n"); } // Clean up xmlXPathFreeContext(user_XP); xmlFreeDoc(user_xml); return 0; } // This function handles activation, deactivation and deletion of an account int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { xmlDoc *user_xml = NULL, *update_xml = NULL, *srch_xml = NULL; xmlNode *user_n = NULL, *update_n = NULL, *srch_root = NULL, *tmp = NULL; char *uid_str = NULL, *activated = NULL, *deactivated = NULL, *actmode_str = NULL, *newpwd = NULL; int i, actmode = 0, rc = 0, crit_set = 0; e_options activargs[] = { {"--uid", "-i", 1}, {"--username", "-u", 1}, {"--new-password", "-P", 1}, {"--help", "-h", 0}, {NULL, NULL, 0} }; assert((ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL)); if( (strcmp(argv[0], "--activate") == 0) || (strcmp(argv[0], "-a") == 0) ) { actmode = 'a'; actmode_str = "activated"; } else if( (strcmp(argv[0], "--deactivate") == 0) || (strcmp(argv[0], "-d") == 0) ) { actmode = 'd'; actmode_str = "deactivated"; } else if( (strcmp(argv[0], "--delete") == 0) || (strcmp(argv[0], "-D") == 0) ) { actmode = 'D'; actmode_str = "deleted"; } else if( (strcmp(argv[0], "--password") == 0) || (strcmp(argv[0], "-p") == 0) ) { actmode = 'p'; actmode_str = "updated with new password"; } else { fprintf(stderr, "%s: System error - illegal users mode'%s'\n", MODULE, argv[0]); return 1; } // Create a fieldMapping XML document, used for searching the user database eurephiaXML_CreateDoc(ctx, 1, "fieldMapping", &srch_xml, &srch_root); xmlNewProp(srch_root, (xmlChar *) "table", (xmlChar *)"users"); // Which table to search in // Argument parsing crit_set = 0; for( i = 1; i < argc; i++ ) { switch( eurephia_getopt(&i, argc, argv, activargs) ) { case 'i': if( atoi_nullsafe(optargs[0]) == 0 ) { fprintf(stderr, "%s: Invalid user id\n", MODULE); return 1; } xmlNewChild(srch_root, NULL, (xmlChar *)"uid", (xmlChar *) optargs[0]); crit_set++; break; case 'u': if( strlen_nullsafe(optargs[0]) < 3 ) { fprintf(stderr, "%s: User name too short\n", MODULE); return 1; } xmlNewChild(srch_root, NULL, (xmlChar *)"username", (xmlChar *)optargs[0]); crit_set++; break; case 'h': display_users_help(actmode); return 0; case 'P': newpwd = strdup_nullsafe(optargs[0]); break; default: return 1; } } // Check if we have the needed search criterias if( crit_set == 0 ) { fprintf(stderr, "%s: Missing required parameter. You must provide either user id or user name\n", MODULE); xmlFreeDoc(srch_xml); return 1; } if( crit_set > 1 ) { fprintf(stderr, "%s: You cannot have several search criterias (-i | -u)\n", MODULE); xmlFreeDoc(srch_xml); return 1; } // Search and find the user which was requested if( (user_xml = eDBadminGetUserInfo(ctx, USERINFO_user, srch_xml)) == NULL ) { fprintf(stderr, "%s: User not found\n", MODULE); xmlFreeDoc(srch_xml); return 1; } xmlFreeDoc(srch_xml); // Parse the user information we received user_n = eurephiaXML_getRoot(ctx, user_xml, "user", 1); if( user_n == NULL ) { eurephia_log(ctx, LOG_ERROR, 0, "%s: Could not find user node in the XML document", MODULE); xmlFreeDoc(user_xml); return 1; } uid_str = xmlGetAttrValue(user_n->properties, "uid"); activated = defaultValue(xmlGetNodeContent(user_n, "activated"), NULL); deactivated = defaultValue(xmlGetNodeContent(user_n, "deactivated"), NULL); // Create a new XML document which will be used to update the user account eurephiaXML_CreateDoc(ctx, 1, "update_user", &update_xml, &update_n); assert( (update_xml != NULL) && (update_n != NULL) ); xmlNewProp(update_n, (xmlChar *) "uid", (xmlChar *) uid_str); // Add fieldMapping - to correctly map eurephia fields into the database fields update_n = xmlNewChild(update_n, NULL, (xmlChar *) "fieldMapping", NULL); xmlNewProp(update_n, (xmlChar *) "table", (xmlChar *) "users"); switch( actmode ) { case 'a': // Activate a user account if( (activated != NULL) && (deactivated == NULL) ) { printf("User account is already active\n"); goto exit; } else { // Set activated field to now() xmlNewChild(update_n, NULL, (xmlChar *) "activated", (xmlChar *) "CURRENT_TIMESTAMP"); // Remove deactivated flag tmp = xmlNewChild(update_n, NULL,(xmlChar *) "deactivated", NULL); xmlNewProp(tmp, (xmlChar *) "setnull", (xmlChar *) "1"); } // Do the update of the user account rc = eDBadminUpdateUser(ctx, atoi_nullsafe(uid_str), update_xml); break; case 'd': // Deactivate a user account if( (activated != NULL) && (deactivated != NULL) ) { printf("User account is already deactived\n"); goto exit; } else if( (activated != NULL) ) { // Set deactivated to now() xmlNewChild(update_n, NULL, (xmlChar *) "deactivated", (xmlChar *) "CURRENT_TIMESTAMP"); } else { fprintf(stderr, "%s: User account is not activated yet\n", MODULE); goto exit; } // Do the update of the user account rc = eDBadminUpdateUser(ctx, atoi_nullsafe(uid_str), update_xml); break; case 'p': // Change password for a user // If we do not have a password .... ask for password via console if( newpwd == NULL ) { char *chkpwd = NULL; newpwd = (char *) malloc(66); assert(newpwd != NULL); memset(newpwd, 0, 66); chkpwd = (char *) malloc(66); assert(chkpwd != NULL); memset(chkpwd, 0, 66); get_console_input(newpwd, 64, "Password for user:", 1); if( strlen_nullsafe(newpwd) < 4 ) { free_nullsafe(newpwd); free_nullsafe(chkpwd); fprintf(stderr, "%s: Password is too short\n", MODULE); goto exit; } get_console_input(chkpwd, 64, "Verify password for user:", 1); if( strcmp(newpwd, chkpwd) != 0 ) { free_nullsafe(newpwd); free_nullsafe(chkpwd); fprintf(stderr, "%s: Passwords didn't match\n", MODULE); goto exit; } free_nullsafe(chkpwd); } // Update with new password tmp = xmlNewChild(update_n, NULL, (xmlChar *) "password", (xmlChar *)newpwd); xmlNewProp(tmp, (xmlChar *) "pwhash", (xmlChar *) "none"); rc = eDBadminUpdateUser(ctx, atoi_nullsafe(uid_str), update_xml); free_nullsafe(newpwd); break; case 'D': // Delete user account xmlFreeDoc(update_xml); // We need another XML doc to delete users eurephiaXML_CreateDoc(ctx, 1, "delete_user", &update_xml, &update_n); assert( (update_xml != NULL) && (update_n != NULL) ); xmlNewProp(update_n, (xmlChar *) "uid", (xmlChar *) uid_str); rc = eDBadminDeleteUser(ctx, atoi_nullsafe(uid_str), update_xml); // Delete links between certificates associated to this user account xmlFreeDoc(update_xml); eurephiaXML_CreateDoc(ctx, 1, "usercerts_link", &update_xml, &update_n); assert( (update_xml != NULL) && (update_n != NULL) ); xmlNewProp(update_n, (xmlChar *) "mode", (xmlChar *) "remove"); update_n = xmlNewChild(update_n, NULL, (xmlChar *) "fieldMapping", NULL); xmlNewProp(update_n, (xmlChar *) "table", (xmlChar *) "usercerts"); xmlNewChild(update_n, NULL, (xmlChar *) "uid", (xmlChar *) uid_str); if( eDBadminUpdateUserCertLink(ctx, update_xml) != 1 ) { fprintf(stderr, "%s: Failed to deregister user <-> certificate link\n", MODULE); } break; } if( rc == 1 ) { printf("User account is %s\n", actmode_str); } else { fprintf(stderr, "%s: Operation failed\n", MODULE); } exit: xmlFreeDoc(user_xml); xmlFreeDoc(update_xml); return (rc != 1); } int add_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { xmlDoc *user_xml = NULL; xmlNode *node = NULL, *node2 = NULL; struct stat cert_stat; int i = 0, certid = 0, uid = 0, certfile_format = CERTFILE_PEM; char *uname = NULL, *passwd = NULL, *certfile = NULL, *digest = NULL; e_options addu_args[] = { {"--username", "-u", 1}, {"--password", "-P", 1}, {"--certid", "-C", 1}, {"--certfile", "-c", 1}, {"--digest", "-d", 1}, {"--pkcs12", "-2", 0}, {"--help", "-h", 0}, {NULL, NULL, 0} }; assert((ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL)); // Parse arguments for( i = 1; i < argc; i++ ) { switch( eurephia_getopt(&i, argc, argv, addu_args) ) { case 'u': if( strlen_nullsafe(optargs[0]) < 3 ) { fprintf(stderr, "%s: username is too short\n", MODULE); return 1; } uname = optargs[0]; break; case 'P': if( strlen_nullsafe(optargs[0]) < 4 ) { fprintf(stderr, "%s: password is too short\n", MODULE); return 1; } passwd = strdup_nullsafe(optargs[0]); break; case 'C': if( (certid = atoi_nullsafe(optargs[0])) < 1 ) { fprintf(stderr, "%s: Invalid certid (numeric value > 0)\n", MODULE); return 1; } break; case 'c': // Check if certfile exists and is readable for us if( strlen_nullsafe(optargs[0]) < 1 ) { fprintf(stderr, "%s: certfile is too short\n", MODULE); return 1; } certfile = optargs[0]; if( stat(certfile, &cert_stat) == -1 ) { fprintf(stderr, "%s: Could not access certfile: %s (%s)\n", MODULE, certfile, strerror(errno)); return 1; } if( cert_stat.st_size == 0 ) { fprintf(stderr, "%s: certfile '%s' is empty\n", MODULE, certfile); return 1; } break; case '2': certfile_format = CERTFILE_PKCS12; break; case 'd': if( strlen_nullsafe(optargs[0]) < 59 ) { fprintf(stderr, "%s: Certificate digest is too short\n", MODULE); return 1; } digest = optargs[0]; break; case 'h': display_users_help('A'); return 0; default: return 1; } } // Make sure received arguments are sane if( uname == NULL ) { fprintf(stderr, "%s: Missing user name\n", MODULE); return 1; } if( ((certid > 0) && (digest != NULL)) || ((certid > 0) && (certfile != NULL)) || ((digest != NULL) && (certfile != NULL)) ) { fprintf(stderr, "%s: --certid, --certfile and --digest cannot be used together\n", MODULE); return 1; } // If we do not have a password .... ask for password via console if( passwd == NULL ) { char *chkpwd = NULL; passwd = (char *) malloc(66); assert(passwd != NULL); memset(passwd, 0, 66); chkpwd = (char *) malloc(66); assert(chkpwd != NULL); memset(chkpwd, 0, 66); get_console_input(passwd, 64, "Password for user:", 1); if( strlen_nullsafe(passwd) < 4 ) { free_nullsafe(passwd); free_nullsafe(chkpwd); fprintf(stderr, "%s: Password is too short\n", MODULE); return 1; } get_console_input(chkpwd, 64, "Verify password for user:", 1); if( strcmp(passwd, chkpwd) != 0 ) { free_nullsafe(passwd); free_nullsafe(chkpwd); fprintf(stderr, "%s: Passwords didn't match\n", MODULE); return 1; } free_nullsafe(chkpwd); } // Prepare add user XML document with fieldMapping eurephiaXML_CreateDoc(ctx, 1, "add_user", &user_xml, &node); node = xmlNewChild(node, NULL, (xmlChar *) "fieldMapping", NULL); xmlNewProp(node, (xmlChar *) "table", (xmlChar *) "users"); xmlNewChild(node, NULL, (xmlChar *) "username", (xmlChar *) uname); node2 = xmlNewChild(node, NULL, (xmlChar *) "password", (xmlChar *) passwd); xmlNewProp(node2, (xmlChar *) "pwhash", (xmlChar *) "none"); // Add the user uid = eDBadminAddUser(ctx, user_xml); if( uid > 0 ) { fprintf(stdout, "%s: User registered successfully (user id %i)\n", MODULE, uid); } else { fprintf(stderr, "%s: Failed to register user\n", MODULE); } memset(passwd, 0, strlen_nullsafe(passwd)); free_nullsafe(passwd); xmlFreeDoc(user_xml); if( (digest != NULL) || (certfile != NULL) ) { if( digest != NULL ) { xmlDoc *cert_xml = NULL, *certlist = NULL; xmlNode *cert_n = NULL; int certcount = 0; // when we have certificate digest, look that up eurephiaXML_CreateDoc(ctx, 1, "certificate_info", &cert_xml, &cert_n); cert_n = xmlNewChild(cert_n, NULL, (xmlChar *) "fieldMapping", NULL); xmlNewProp(cert_n, (xmlChar *) "table", (xmlChar *) "certificates"); xmlNewChild(cert_n, NULL, (xmlChar *) "digest", (xmlChar *) digest); certlist = eDBadminGetCertificateInfo(ctx, cert_xml, "certid"); if( certlist == NULL ) { fprintf(stderr, "%s: Error while looking up certificate info.\n" "%s: User account is not associated with any certificates\n", MODULE, MODULE); xmlFreeDoc(cert_xml); goto exit; } xmlFreeDoc(cert_xml); cert_n = eurephiaXML_getRoot(ctx, certlist, "certificates", 1); if( cert_n == NULL ) { fprintf(stderr, "%s: Could not find certificates root node in XML document. " "No association done.\n", MODULE); xmlFreeDoc(certlist); goto exit; } certcount = atoi_nullsafe(xmlGetAttrValue(cert_n->properties, "certificates")); if( certcount == 0) { fprintf(stderr, "%s: No certificates was found. No association is done.\n", MODULE); xmlFreeDoc(certlist); goto exit; } else if( certcount > 1 ) { fprintf(stderr, "%s: More than one certificates was found. " "No association is done.\n", MODULE); xmlFreeDoc(certlist); goto exit; } // Get the first and only certificate node cert_n = xmlFindNode(cert_n, "certificate"); if( cert_n == NULL ) { fprintf(stderr, "%s: Could not find certificate node in XML document. " "No association done.\n", MODULE); xmlFreeDoc(certlist); goto exit; } // finally, we should have located the certid in the XML certid = atoi_nullsafe(xmlGetAttrValue(cert_n->properties, "certid")); xmlFreeDoc(certlist); } else if( certfile != NULL ) { // when we have certfile - register the certificate and register the link certinfo *ci = NULL; ci = Cert_ParseFile(certfile, certfile_format); if( ci == NULL ) { fprintf(stderr, "%s: Could not parse the certificate file. " "No association done.\n", MODULE); goto exit; } certid = register_certificate(ctx, 0, ci->digest, ci->common_name, ci->org, ci->email); if( certid == 0 ) { fprintf(stderr, "%s: Failed to register certificate file. No association done.", MODULE); } } } // If we have a certificate id, register a certificate link to the user account if( (certid > 0) && (uid > 0) ) { xmlDoc *usercert_xml = NULL; xmlNode *usercert_n = NULL; xmlChar tmp[66]; memset(&tmp, 0, 66); eurephiaXML_CreateDoc(ctx, 1, "usercerts_link", &usercert_xml, &usercert_n); assert( (usercert_xml != NULL) && (usercert_n != NULL) ); xmlNewProp(usercert_n, (xmlChar *) "mode", (xmlChar *) "register"); usercert_n = xmlNewChild(usercert_n, NULL, (xmlChar *) "fieldMapping", NULL); xmlNewProp(usercert_n, (xmlChar *) "table", (xmlChar *) "usercerts"); xmlStrPrintf(tmp, 64, (xmlChar *) "%i%c", uid, '\0'); xmlNewChild(usercert_n, NULL, (xmlChar *) "uid", tmp); xmlStrPrintf(tmp, 64, (xmlChar *) "%i%c", certid, '\0'); xmlNewChild(usercert_n, NULL, (xmlChar *) "certid", tmp); if( eDBadminUpdateUserCertLink(ctx, usercert_xml) < 1 ) { fprintf(stderr, "%s: Failed to register user <-> certificate link\n", MODULE); } } exit: return (uid > 0); } int cmd_Users(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { char **mode_argv; int i, mode_argc = 0, rc = 0; int (*mode_fnc) (eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv); e_options modeargs[] = { {"--list", "-l", 0}, {"--show", "-s", 0}, {"--activate", "-a", 0}, {"--deactivate", "-d", 0}, {"--add", "-A", 0}, {"--delete", "-D", 0}, {"--password", "-p", 0}, {"--help", "-h", 0}, {NULL, NULL, 0} }; assert((ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL)); mode_fnc = NULL; for( i = 1; i < argc; i++ ) { switch( eurephia_getopt(&i, argc, argv, modeargs) ) { case 'l': mode_fnc = list_users; break; case 's': mode_fnc = show_user; break; case 'a': mode_fnc = account_activation; break; case 'd': mode_fnc = account_activation; break; case 'h': mode_fnc = help_Users2; break; case 'A': mode_fnc = add_user; break; case 'D': mode_fnc = account_activation; break; case 'p': mode_fnc = account_activation; break; default: break; } if( mode_fnc != NULL ) { break; } } // If we do not have any known mode defined, exit with error if( mode_fnc == NULL ) { fprintf(stderr, "Unknown argument. No mode given\n"); return 1; } // Allocate memory for our arguments being sent to the mode function mode_argv = (char **) calloc(sizeof(char *), (argc - i)+2); assert(mode_argv != NULL); // Copy over only the arguments needed for the mode mode_argc = eurephia_arraycp(i, argc, argv, mode_argv, (argc - i)); // Call the mode function rc = mode_fnc(ctx, sess, cfg, mode_argc, mode_argv); free_nullsafe(mode_argv); return rc; }