users.c

Go to the documentation of this file.
00001 /* users.c  --  eurephiadm command - User Account Management
00002  *
00003  *  GPLv2 only - Copyright (C) 2008 - 2010
00004  *               David Sommerseth <dazo@users.sourceforge.net>
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; version 2
00009  *  of the License.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00019  *
00020  */
00021 
00031 #include <stdio.h>
00032 #include <string.h>
00033 #include <sys/stat.h>
00034 #include <errno.h>
00035 #include <assert.h>
00036 
00037 #ifdef HAVE_LIBXML2
00038 #include <libxml/tree.h>
00039 #include <libxml/xpath.h>
00040 #endif
00041 
00042 #define MODULE "eurephia::Users" 
00043 #include <eurephia_nullsafe.h>
00044 #include <eurephia_context.h>
00045 #include <eurephia_log.h>
00046 #include <eurephia_xml.h>
00047 #include <eurephia_values_struct.h>
00048 #include <eurephiadb_session_struct.h>
00049 #include <eurephiadb_mapping.h>
00050 #include <eurephiadb_driver.h>
00051 #include <certinfo.h>
00052 
00053 #include "../argparser.h"
00054 #include "../get_console_input.h"
00055 #include "../parse_certificate_files.h"
00056 #include "../xsltparser.h"
00057 
00058 
00062 int register_certificate(eurephiaCTX *ctx, int depth, const char *digest,
00063                          const char *cname, const char *org, const char *email);
00064 
00065 
00071 void display_users_help(int page) {
00072         printf("\n%s -- Administer user accounts\n\n", MODULE);
00073 
00074         switch( page ) {
00075         case 'l':
00076                 printf("The list mode can accept one parameter:\n\n"
00077                        "     -S | --sort <sort key>     Decide the sort order of the user list\n"
00078                        "\n"
00079                        "Available sort keys are: uid, username, activated, deactivated and lastaccess\n\n");
00080                 break;
00081 
00082         case 's':
00083                 printf("The show mode shows more information about a user account.\n"
00084                        "One of the following arguments are required:\n\n"
00085                        "     -i | --uid              Numeric user ID\n"
00086                        "     -u | --username         User name\n"
00087                        "\n"
00088                        "Optional arguments are:\n\n"
00089                        "     -l | --lastlog          Show users lastlog entries\n"
00090                        "     -L | --lastlog-details  Show a more verbose lastlog\n"
00091                        "     -a | --attempts         Show users failed attempts and blacklisting\n"
00092                        "     -b | --blacklist        Alias for --attempts\n"
00093                        "\n");
00094                 break;
00095 
00096         case 'a':
00097                 printf("The activate mode activates an account which not activated or deactivated.\n"
00098                        "One of the following arguments are required:\n\n"
00099                        "     -i | --uid          Numeric user ID\n"
00100                        "     -u | --username     User name\n\n");
00101                 break;
00102 
00103         case 'd':
00104                 printf("The deactivate mode deactivates a user account.\n"
00105                        "One of the following arguments are required:\n\n"
00106                        "     -i | --uid          Numeric user ID\n"
00107                        "     -u | --username     User name\n\n");
00108                 break;
00109 
00110         case 'A':
00111                 printf("The add user mode registers a new user account.\n"
00112                        "Both of the following arguments are required:\n\n"
00113                        "     -u | --username     User name to use for the new account (required)\n"
00114                        "     -P | --password     Assign a new password via the command line.\n\n"
00115                        "To register this new account against a certificate you can use the\n"
00116                        "following arguments.  These arguments cannot be used together.\n\n"
00117                        "     -C | --certid       Use already registered certificate, identified by certid.\n"
00118                        "     -D | --digest       Use already registered certificate, identified by digest.\n"
00119                        "     -c | --certfile     Use the given certificate file and register it along with\n"
00120                        "                         the account.\n"
00121                        "     -2 | --pkcs12       Certificate file is using the PKCS#12 format.\n\n");
00122                 break;
00123 
00124         case 'D':
00125                 printf("The delete user mode will delete a user account from the database.\n"
00126                        "One of the following arguments are required:\n\n"
00127                        "     -i | --uid          Numeric user ID\n"
00128                        "     -u | --username     User name\n\n");
00129                 break;
00130 
00131         case 'p':
00132                 printf("The change password mode is used for changing password for other\n"
00133                        "persons than yourself.\n\n"
00134                        "One of the following arguments are required:\n\n"
00135                        "     -i | --uid          Numeric user ID\n"
00136                        "     -u | --username     User name\n\n");
00137                 break;
00138 
00139         default:
00140                 printf("Available modes:\n"
00141                        "     -l | --list         List all user accounts\n"
00142                        "     -s | --show         Show user account details\n"
00143                        "     -a | --activate     Activate a user account\n"
00144                        "     -d | --deactivate   Deactivate a user account\n"
00145                        "     -A | --add          Add a new user account\n"
00146                        "     -D | --delete       Delete a user account\n"
00147                        "     -p | --password     Change password on a users account\n"
00148                        "     -h | --help <mode>  Further help for these modes\n\n");
00149                 break;
00150         }
00151 }
00152 
00153 
00165 int help_Users2(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) {
00166         e_options helpargs[] = {
00167                 {"--list", "-l", 0},
00168                 {"--show", "-s", 0},
00169                 {"--activate", "-a", 0},
00170                 {"--deactivate", "-d", 0},
00171                 {"--add", "-A", 0},
00172                 {"--delete", "-D", 0},
00173                 {"--password", "-p", 0},
00174                 {NULL, NULL, 0}
00175         };
00176 
00177         int i = 1;
00178         display_users_help(eurephia_getopt(&i, argc, argv, helpargs));
00179         return 0;
00180 }
00181 
00185 void help_Users() {
00186         display_users_help(0);
00187 }
00188 
00189 
00201 int list_users(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) {
00202         xmlDoc *qrydoc = NULL, *userlist = NULL;
00203         xmlNode *qry_n = NULL, *fmap_n = NULL;
00204         int i = 0, rc = 0;
00205         char *sortkeys = NULL;
00206         const char *xsltparams[] = {"view", "'userlist'", NULL};
00207 
00208         e_options listargs[] = {
00209                 {"--sort", "-S", 1},
00210                 {"--help", "-h", 0},
00211                 {NULL, NULL, 0}
00212         };
00213 
00214         assert((ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL));
00215 
00216         // Parse arguments
00217         for( i = 1; i < argc; i++ ) {
00218                 switch( eurephia_getopt(&i, argc, argv, listargs) ) {
00219                 case 'S':
00220                         sortkeys = optargs[0];
00221                         i++;
00222                         break;
00223 
00224                 case 'h':
00225                         display_users_help('l');
00226                         return 0;
00227 
00228                 default:
00229                         return 1;
00230                 }
00231         }
00232 
00233         // Create a query document
00234         eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &qrydoc, &qry_n);
00235         assert( (qrydoc != NULL) && (qry_n != NULL) );
00236 
00237         xmlNewProp(qry_n, (xmlChar *) "mode", (xmlChar *) "view");
00238         xmlNewChild(qry_n, NULL, (xmlChar *) "sortkeys", (xmlChar *)sortkeys);
00239         xmlNewChild(qry_n, NULL, (xmlChar *) "extractFlags", (xmlChar *) "1");
00240 
00241         fmap_n = xmlNewChild(qry_n, NULL, (xmlChar *) "fieldMapping", NULL);
00242         assert( fmap_n != NULL );
00243         xmlNewProp(fmap_n, (xmlChar *) "table", (xmlChar *) "users");
00244 
00245         // Retrieve the user list - and display it
00246         userlist = eDBadminUserAccount(ctx, qrydoc);
00247         if( eurephiaXML_IsResultMsg(ctx, userlist) ) {
00248                 eurephiaRESULT *res = eurephiaXML_ParseResultMsg(ctx, userlist);
00249                 if( res->resultType == exmlERROR ) {
00250                         fprintf(stderr, "%s: %s\n", MODULE, res->message);
00251                         rc = 1;
00252                 } else {
00253                         rc = 2;
00254                 }
00255                 free_nullsafe(ctx, res);
00256         } else {
00257                 xslt_print_xmldoc(stdout, cfg, userlist, "users.xsl", xsltparams);
00258                 rc = 0;
00259         }
00260         xmlFreeDoc(userlist);
00261         xmlFreeDoc(qrydoc);
00262 
00263         return rc;
00264 }
00265 
00266 
00278 int show_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) {
00279         int i, crit_set = 0, lastlog_verb = 0;
00280         long int show_info = USERINFO_user | USERINFO_certs;
00281         xmlDoc *user_xml = NULL, *srch_xml = NULL;
00282         xmlNode *srch_root = NULL, *fmap_n = NULL;
00283         xmlChar flags[34];
00284 
00285 #ifdef FIREWALL
00286         const char *xsltparams[] = {"view", NULL, "firewall", "'1'", "view_digest", "'0'", NULL};
00287 #else
00288         const char *xsltparams[] = {"view", NULL, "firewall", "'0'", "view_digest", "'0'", NULL};
00289 #endif
00290 
00291         e_options activargs[] = {
00292                 {"--uid", "-i", 1},
00293                 {"--username", "-u", 1},
00294                 {"--lastlog", "-l", 0},
00295                 {"--lastlog-details", "-L", 0},
00296                 {"--attempts", "-a", 0},
00297                 {"--blacklist", "-b", 0}, // Alias for -a | --attempts
00298                 {"--help", "-h", 0},
00299                 {NULL, NULL, 0}
00300         };
00301 
00302         assert((ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL));
00303 
00304 
00305         // Create a UserAccount query XML document
00306         eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &srch_xml, &srch_root);
00307         xmlNewProp(srch_root, (xmlChar*) "mode", (xmlChar *) "view");
00308 
00309         // Setup the fieldMapping - to narrow the search
00310         fmap_n = xmlNewChild(srch_root, NULL, (xmlChar *) "fieldMapping", NULL);
00311         xmlNewProp(fmap_n, (xmlChar *) "table", (xmlChar *)"users");
00312 
00313         // Argument parsing
00314         crit_set = 0;
00315         for( i = 1; i < argc; i++ ) {
00316                 switch( eurephia_getopt(&i, argc, argv, activargs) ) {
00317                 case 'i':
00318                         if( atoi_nullsafe(optargs[0]) == 0 ) {
00319                                 fprintf(stderr, "%s: Invalid user id\n", MODULE);
00320                                 return 1;
00321                         }
00322                         xmlNewChild(fmap_n, NULL, (xmlChar *)"uid", (xmlChar *) optargs[0]);
00323                         crit_set++;
00324                         break;
00325 
00326                 case 'u':
00327                         if( strlen_nullsafe(optargs[0]) < 3 ) {
00328                                 fprintf(stderr, "%s: User name too short\n", MODULE);
00329                                 return 1;
00330                         }
00331                         xmlNewChild(fmap_n, NULL, (xmlChar *)"username", (xmlChar *)optargs[0]);
00332                         crit_set++;
00333                         break;
00334 
00335                 case 'a':
00336                 case 'b':
00337                         show_info = USERINFO_attempts | USERINFO_blacklist;
00338                         break;
00339 
00340                 case 'L':
00341                         lastlog_verb = 1;
00342                 case 'l':
00343                         show_info = USERINFO_lastlog;
00344                         break;
00345 
00346                 case 'h':
00347                         display_users_help('s');
00348                         return 0;
00349 
00350                 default:
00351                         return 1;
00352                 }
00353         }
00354 
00355         // Check if we have the needed search criteria
00356         if( crit_set == 0 ) {
00357                 fprintf(stderr,
00358                         "%s:  Missing required parameter.  You must provide either user id or user name\n",
00359                         MODULE);
00360                 xmlFreeDoc(srch_xml);
00361                 return 1;
00362         }
00363 
00364         if( crit_set > 1 ) {
00365                 fprintf(stderr,
00366                         "%s: You cannot have several search criteria (-i | -u)\n", MODULE);
00367                 xmlFreeDoc(srch_xml);
00368                 return 1;
00369         }
00370 
00371         xmlStrPrintf(flags, 32, (xmlChar *) "%ld%c", show_info, 0);
00372         xmlNewChild(srch_root, NULL, (xmlChar *) "extractFlags", flags);
00373 
00374         // Do the query against the database
00375         if( (user_xml = eDBadminUserAccount(ctx, srch_xml)) == NULL )  {
00376                 xmlFreeDoc(srch_xml);
00377                 fprintf(stderr, "%s: User not found\n", MODULE);
00378                 return 1;
00379         }
00380         xmlFreeDoc(srch_xml);
00381 
00382         if( eurephiaXML_IsResultMsg(ctx, user_xml) ) {
00383                 eurephiaRESULT *res = eurephiaXML_ParseResultMsg(ctx, user_xml);
00384                 if( res->resultType == exmlERROR ) {
00385                         fprintf(stderr, "%s: %s\n", MODULE, res->message);
00386                         free_nullsafe(ctx, res);
00387                         xmlFreeDoc(user_xml);
00388                         return 1;
00389                 }
00390                 free_nullsafe(ctx, res);
00391         }
00392 
00393         if( show_info & USERINFO_user ) {
00394                 xsltparams[1] = "'userinfo'";
00395                 xslt_print_xmldoc(stdout, cfg, user_xml, "users.xsl", xsltparams);
00396         }
00397 
00398         // Show associated certificates if we was asked to show this info
00399         if( show_info & USERINFO_certs ) {
00400                 xsltparams[1] = "''";
00401                 xslt_print_xmldoc(stdout, cfg, user_xml, "certificates.xsl", xsltparams);
00402         }
00403 
00404         // Show lastlog for the user, if requested
00405         if( show_info & USERINFO_lastlog ) {
00406                 xmlNode *user_n = NULL;
00407 
00408                 xsltparams[1] = "'list'";
00409                 if( lastlog_verb ) {
00410                         xsltparams[1] = "'details'";
00411                 }
00412 
00413                 user_n = eurephiaXML_getRoot(ctx, user_xml, "UserAccount", 1);
00414                 user_n = xmlFindNode(user_n, "Account");
00415                 if( user_n == NULL ) {
00416                         fprintf(stderr, "Could not retrieve valid data\n");
00417                         xmlFreeDoc(user_xml);
00418                         return 1;
00419                 }
00420 
00421                 printf("** Lastlog entries for %s\n\n", xmlGetNodeContent(user_n, "username"));
00422 
00423                 xslt_print_xmldoc(stdout, cfg, user_xml, "lastlog.xsl", xsltparams);
00424         }
00425 
00426         // Show login attempt info and/or blacklist info
00427         if( (show_info & USERINFO_attempts) || (show_info & USERINFO_blacklist) ) {
00428                 xsltparams[1] = "'attemptblacklist'";
00429                 xslt_print_xmldoc(stdout, cfg, user_xml, "users.xsl", xsltparams);
00430         }
00431 
00432         // Clean up
00433         xmlFreeDoc(user_xml);
00434 
00435         return 0;
00436 }
00437 
00438 
00450 int account_activation(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) {
00451         xmlDoc *user_xml = NULL, *update_xml = NULL, *srch_xml = NULL, *tmp_xml = NULL, *res_xml = NULL;
00452         xmlNode *user_n = NULL, *update_n = NULL, *srch_root = NULL, *tmp_n = NULL, *fmap_n = NULL;
00453         eurephiaRESULT *res = NULL;
00454         char *uid_str = NULL, *activated = NULL, *deactivated = NULL, *actmode_str = NULL, *newpwd = NULL;
00455         int i, actmode = 0, rc = 0, crit_set = 0;
00456         xmlChar flags[34];
00457 
00458         e_options activargs[] = {
00459                 {"--uid", "-i", 1},
00460                 {"--username", "-u", 1},
00461                 {"--new-password", "-P", 1},
00462                 {"--help", "-h", 0},
00463                 {NULL, NULL, 0}
00464         };
00465 
00466         assert((ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL));
00467 
00468         if( (strcmp(argv[0], "--activate") == 0) || (strcmp(argv[0], "-a") == 0) ) {
00469                 actmode = 'a';
00470                 actmode_str = "activated";
00471         } else if( (strcmp(argv[0], "--deactivate") == 0) || (strcmp(argv[0], "-d") == 0) ) {
00472                 actmode = 'd';
00473                 actmode_str = "deactivated";
00474         } else if( (strcmp(argv[0], "--delete") == 0) || (strcmp(argv[0], "-D") == 0) ) {
00475                 actmode = 'D';
00476                 actmode_str = "deleted";
00477         } else if( (strcmp(argv[0], "--password") == 0) || (strcmp(argv[0], "-p") == 0) ) {
00478                 actmode = 'p';
00479                 actmode_str = "updated with new password";
00480         } else {
00481                 fprintf(stderr, "%s: System error - illegal users mode'%s'\n", MODULE, argv[0]);
00482                 return 1;
00483         }
00484 
00485         // Create a UserAccount query XML document
00486         eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &srch_xml, &srch_root);
00487         xmlNewProp(srch_root, (xmlChar*) "mode", (xmlChar *) "view");
00488 
00489         // Setup the fieldMapping - to narrow the search
00490         fmap_n = xmlNewChild(srch_root, NULL, (xmlChar *) "fieldMapping", NULL);
00491         xmlNewProp(fmap_n, (xmlChar *) "table", (xmlChar *)"users");
00492 
00493         xmlStrPrintf(flags, 32, (xmlChar *) "%ld%c", USERINFO_user, 0);
00494         xmlNewChild(srch_root, NULL, (xmlChar *) "extractFlags", flags);
00495 
00496         // Argument parsing
00497         crit_set = 0;
00498         for( i = 1; i < argc; i++ ) {
00499                 switch( eurephia_getopt(&i, argc, argv, activargs) ) {
00500                 case 'i':
00501                         if( atoi_nullsafe(optargs[0]) == 0 ) {
00502                                 fprintf(stderr, "%s: Invalid user id\n", MODULE);
00503                                 return 1;
00504                         }
00505                         xmlNewChild(fmap_n, NULL, (xmlChar *)"uid", (xmlChar *) optargs[0]);
00506                         crit_set++;
00507                         break;
00508 
00509                 case 'u':
00510                         if( strlen_nullsafe(optargs[0]) < 3 ) {
00511                                 fprintf(stderr, "%s: User name too short\n", MODULE);
00512                                 return 1;
00513                         }
00514                         xmlNewChild(fmap_n, NULL, (xmlChar *)"username", (xmlChar *)optargs[0]);
00515                         crit_set++;
00516                         break;
00517 
00518                 case 'h':
00519                         display_users_help(actmode);
00520                         return 0;
00521 
00522                 case 'P':
00523                         newpwd = strdup_nullsafe(optargs[0]);
00524                         break;
00525 
00526                 default:
00527                         return 1;
00528                 }
00529         }
00530 
00531         // Check if we have the needed search criteria
00532         if( crit_set == 0 ) {
00533                 fprintf(stderr,
00534                         "%s:  Missing required parameter.  You must provide either user id or user name\n",
00535                         MODULE);
00536                 xmlFreeDoc(srch_xml);
00537                 return 1;
00538         }
00539 
00540         if( crit_set > 1 ) {
00541                 fprintf(stderr,
00542                         "%s: You cannot have several search criteria (-i | -u)\n", MODULE);
00543                 xmlFreeDoc(srch_xml);
00544                 return 1;
00545         }
00546 
00547         // Do the query against the database
00548         if( (user_xml = eDBadminUserAccount(ctx, srch_xml)) == NULL )  {
00549                 xmlFreeDoc(srch_xml);
00550                 fprintf(stderr, "%s: User not found\n", MODULE);
00551                 return 1;
00552         }
00553         xmlFreeDoc(srch_xml);
00554 
00555         if( eurephiaXML_IsResultMsg(ctx, user_xml) ) {
00556                 eurephiaRESULT *res = eurephiaXML_ParseResultMsg(ctx, user_xml);
00557                 if( res->resultType == exmlERROR ) {
00558                         fprintf(stderr, "%s: %s\n", MODULE, res->message);
00559                         free_nullsafe(ctx, res);
00560                         xmlFreeDoc(user_xml);
00561                         return 1;
00562                 }
00563                 free_nullsafe(ctx, res);
00564         }
00565 
00566         user_n = eurephiaXML_getRoot(ctx, user_xml, "UserAccount", 1);
00567         user_n = xmlFindNode(user_n, "Account");
00568         if( user_n == NULL ) {
00569                 xmlFreeDoc(user_xml);
00570                 fprintf(stderr, "%s: No user account information found\n", MODULE);
00571                 return 1;
00572         }
00573         uid_str     = xmlGetAttrValue(user_n->properties, "uid");
00574         activated   = defaultValue(xmlGetNodeContent(user_n, "activated"), NULL);
00575         deactivated = defaultValue(xmlGetNodeContent(user_n, "deactivated"), NULL);
00576 
00577         // Create a new XML document which will be used to update the user account
00578         eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &update_xml, &update_n);
00579         assert( (update_xml != NULL) && (update_n != NULL) );
00580         xmlNewProp(update_n, (xmlChar *) "mode", (xmlChar *) "update");
00581         xmlNewProp(update_n, (xmlChar *) "uid", (xmlChar *) uid_str);
00582 
00583         // Add fieldMapping - to correctly map eurephia fields into the database fields
00584         update_n = xmlNewChild(update_n, NULL, (xmlChar *) "fieldMapping", NULL);
00585         xmlNewProp(update_n, (xmlChar *) "table", (xmlChar *) "users");
00586 
00587         switch( actmode ) {
00588         case 'a':  // Activate a user account
00589                 if( (activated != NULL)  && (deactivated == NULL) ) {
00590                         printf("%s: User account is already active\n", MODULE);
00591                         goto exit;
00592                 } else {
00593                         // Set activated field to now()
00594                         xmlNewChild(update_n, NULL,
00595                                      (xmlChar *) "activated", (xmlChar *) "CURRENT_TIMESTAMP");
00596 
00597                         // Remove deactivated flag
00598                         tmp_n = xmlNewChild(update_n, NULL,(xmlChar *) "deactivated", NULL);
00599                         xmlNewProp(tmp_n, (xmlChar *) "setnull", (xmlChar *) "1");
00600                 }
00601 
00602                 // Do the update of the user account
00603                 res_xml = eDBadminUserAccount(ctx, update_xml);
00604                 break;
00605 
00606         case 'd':  // Deactivate a user account
00607                 if( (activated != NULL)  && (deactivated != NULL) ) {
00608                         printf("User account is already deactivated\n");
00609                         goto exit;
00610                 } else if( (activated != NULL) ) {
00611                         // Set deactivated to now()
00612                         xmlNewChild(update_n, NULL,
00613                                      (xmlChar *) "deactivated", (xmlChar *) "CURRENT_TIMESTAMP");
00614 
00615                 } else {
00616                         fprintf(stderr, "%s: User account is not activated yet\n", MODULE);
00617                         goto exit;
00618                 }
00619 
00620                 // Do the update of the user account
00621                 res_xml = eDBadminUserAccount(ctx, update_xml);
00622                 break;
00623 
00624         case 'p':  // Change password for a user
00625 
00626                 // If we do not have a password .... ask for password via console
00627                 if( newpwd == NULL ) {
00628                         char *chkpwd = NULL;
00629 
00630                         newpwd = (char *) malloc_nullsafe(ctx, 66);
00631                         assert(newpwd != NULL);
00632                         chkpwd = (char *) malloc_nullsafe(ctx, 66);
00633                         assert(chkpwd != NULL);
00634 
00635                         get_console_input(newpwd, 64, "Password for user:", 1);
00636                         if( strlen_nullsafe(newpwd) < 4 ) {
00637                                 free_nullsafe(ctx, newpwd);
00638                                 free_nullsafe(ctx, chkpwd);
00639                                 fprintf(stderr, "%s: Password is too short\n", MODULE);
00640                                 goto exit;
00641                         }
00642 
00643                         get_console_input(chkpwd, 64, "Verify password for user:", 1);
00644                         if( strcmp(newpwd, chkpwd) != 0 ) {
00645                                 free_nullsafe(ctx, newpwd);
00646                                 free_nullsafe(ctx, chkpwd);
00647                                 fprintf(stderr, "%s: Passwords didn't match\n", MODULE);
00648                                 goto exit;
00649                         }
00650                         free_nullsafe(ctx, chkpwd);
00651                 }
00652 
00653                 // Update with new password
00654                 tmp_n = xmlNewChild(update_n, NULL, (xmlChar *) "password", (xmlChar *)newpwd);
00655                 xmlNewProp(tmp_n, (xmlChar *) "pwhash", (xmlChar *) "none");
00656                 res_xml = eDBadminUserAccount(ctx, update_xml);
00657 
00658                 free_nullsafe(ctx, newpwd);
00659                 break;
00660 
00661         case 'D':  // Delete user account
00662                 xmlFreeDoc(update_xml); // We need another XML doc to delete users
00663 
00664                 eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &update_xml, &update_n);
00665                 assert( (update_xml != NULL) && (update_n != NULL) );
00666                 xmlNewProp(update_n, (xmlChar *) "mode", (xmlChar *) "delete");
00667                 xmlNewProp(update_n, (xmlChar *) "uid", (xmlChar *) uid_str);
00668                 update_n = xmlNewChild(update_n, NULL, (xmlChar *) "fieldMapping", NULL);
00669                 xmlNewProp(update_n, (xmlChar *) "table", (xmlChar *) "users");
00670 
00671                 res_xml = eDBadminUserAccount(ctx, update_xml);
00672 
00673                 // Check if this update failed and abort further operations if it did
00674                 if( eurephiaXML_IsResultMsg(ctx, res_xml) ) {
00675                         res = eurephiaXML_ParseResultMsg(ctx, res_xml);
00676                         if( (res == NULL) || (res->resultType == exmlERROR) ) {
00677                                 free_nullsafe(ctx, res);
00678                                 break;
00679                         }
00680                         free_nullsafe(ctx, res);
00681                 } else {
00682                         // No ResultMsg document was returned, which is also wrong.
00683                         break;
00684                 }
00685                 // Delete links between certificates associated to this user account
00686                 xmlFreeDoc(update_xml);
00687                 eurephiaXML_CreateDoc(ctx, 1, "usercerts", &update_xml, &update_n);
00688                 assert( (update_xml != NULL) && (update_n != NULL) );
00689 
00690                 xmlNewProp(update_n, (xmlChar *) "mode", (xmlChar *) "remove");
00691                 update_n = xmlNewChild(update_n, NULL, (xmlChar *) "fieldMapping", NULL);
00692                 xmlNewProp(update_n, (xmlChar *) "table", (xmlChar *) "usercerts");
00693                 xmlNewChild(update_n, NULL, (xmlChar *) "uid", (xmlChar *) uid_str);
00694 
00695                 tmp_xml = eDBadminUserCertsLink(ctx, update_xml);
00696                 res = eurephiaXML_ParseResultMsg(ctx, tmp_xml);
00697                 if( res == NULL ) {
00698                         fprintf(stderr, "%s: Failed to remove user <-> certificate link.  "
00699                                 "No results received\n", MODULE);
00700                         rc = 0;
00701                 } else if( res->resultType == exmlERROR ) {
00702                         fprintf(stderr, "%s: %s\n", MODULE, res->message);
00703                 } else {
00704                         fprintf(stdout, "%s: %s\n", MODULE, res->message);
00705                         rc = 1;
00706                 }
00707                 free_nullsafe(ctx, res);
00708                 xmlFreeDoc(tmp_xml);
00709                 break;
00710         }
00711 
00712         if( eurephiaXML_IsResultMsg(ctx, res_xml) ) {
00713                 eurephiaRESULT *res = eurephiaXML_ParseResultMsg(ctx, res_xml);
00714                 if( res->resultType == exmlERROR ) {
00715                         fprintf(stderr, "%s: %s\n", MODULE, res->message);
00716                         rc = 0;
00717                 } else {
00718                         fprintf(stdout, "%s: %s\n", MODULE, res->message);
00719                         rc = 1;
00720                 }
00721                 free_nullsafe(ctx, res);
00722         } else {
00723                 fprintf(stderr, "%s: Unknown error\n", MODULE);
00724         }
00725         xmlFreeDoc(res_xml);
00726 
00727  exit:
00728         xmlFreeDoc(user_xml);
00729         xmlFreeDoc(update_xml);
00730         return (rc != 1);
00731 }
00732 
00733 
00745 int add_user(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) {
00746         xmlDoc *user_xml = NULL, *resxml = NULL;
00747         xmlNode *node = NULL, *node2 = NULL;
00748         eurephiaRESULT *res = NULL;
00749         struct stat cert_stat;
00750         int i = 0, certid = 0, uid = 0, certfile_format = CERTFILE_PEM;
00751         char *uname = NULL, *passwd = NULL, *certfile = NULL, *digest = NULL;
00752 
00753         e_options addu_args[] = {
00754                 {"--username", "-u", 1},
00755                 {"--password", "-P", 1},
00756                 {"--certid",   "-C", 1},
00757                 {"--certfile", "-c", 1},
00758                 {"--digest",   "-D", 1},
00759                 {"--pkcs12",   "-2", 0},
00760                 {"--help", "-h", 0},
00761                 {NULL, NULL, 0}
00762         };
00763 
00764         assert((ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL));
00765 
00766         // Parse arguments
00767         for( i = 1; i < argc; i++ ) {
00768                 switch( eurephia_getopt(&i, argc, argv, addu_args) ) {
00769                 case 'u':
00770                         if( strlen_nullsafe(optargs[0]) < 3 ) {
00771                                 fprintf(stderr, "%s: username is too short\n", MODULE);
00772                                 return 1;
00773                         }
00774                         uname = optargs[0];
00775                         break;
00776 
00777                 case 'P':
00778                         if( strlen_nullsafe(optargs[0]) < 4 ) {
00779                                 fprintf(stderr, "%s: password is too short\n", MODULE);
00780                                 return 1;
00781                         }
00782                         passwd = strdup_nullsafe(optargs[0]);
00783                         break;
00784 
00785                 case 'C':
00786                         if( (certid = atoi_nullsafe(optargs[0])) < 1 ) {
00787                                 fprintf(stderr, "%s: Invalid certid (numeric value > 0)\n", MODULE);
00788                                 return 1;
00789                         }
00790                         break;
00791 
00792                 case 'c': // Check if certfile exists and is readable for us
00793                         if( strlen_nullsafe(optargs[0]) < 1 ) {
00794                                 fprintf(stderr, "%s: certfile is too short\n", MODULE);
00795                                 return 1;
00796                         }
00797                         certfile = optargs[0];
00798 
00799                         if( stat(certfile, &cert_stat) == -1 ) {
00800                                 fprintf(stderr, "%s: Could not access certfile: %s (%s)\n", MODULE,
00801                                         certfile, strerror(errno));
00802                                 return 1;
00803                         }
00804 
00805                         if( cert_stat.st_size == 0 ) {
00806                                 fprintf(stderr, "%s: certfile '%s' is empty\n", MODULE, certfile);
00807                                 return 1;
00808                         }
00809                         break;
00810 
00811                 case '2':
00812                         certfile_format = CERTFILE_PKCS12;
00813                         break;
00814 
00815                 case 'D':
00816                         if( strlen_nullsafe(optargs[0]) < 59 ) {
00817                                 fprintf(stderr, "%s: Certificate digest is too short\n", MODULE);
00818                                 return 1;
00819                         }
00820                         digest = optargs[0];
00821                         break;
00822 
00823                 case 'h':
00824                         display_users_help('A');
00825                         return 0;
00826 
00827                 default:
00828                         return 1;
00829                 }
00830         }
00831 
00832         // Make sure received arguments are sane
00833         if( uname == NULL ) {
00834                 fprintf(stderr, "%s: Missing user name\n", MODULE);
00835                 return 1;
00836         }
00837 
00838         if( ((certid > 0) && (digest != NULL))
00839             || ((certid > 0) && (certfile != NULL))
00840             || ((digest != NULL) && (certfile != NULL)) ) {
00841                 fprintf(stderr, "%s: --certid, --certfile and --digest cannot be used together\n", MODULE);
00842                 return 1;
00843         }
00844 
00845         // If we do not have a password .... ask for password via console
00846         if( passwd == NULL ) {
00847                 char *chkpwd = NULL;
00848 
00849                 passwd = (char *) malloc_nullsafe(ctx, 66);
00850                 assert(passwd != NULL);
00851 
00852                 chkpwd = (char *) malloc_nullsafe(ctx, 66);
00853                 assert(chkpwd != NULL);
00854 
00855                 get_console_input(passwd, 64, "Password for user:", 1);
00856                 if( strlen_nullsafe(passwd) < 4 ) {
00857                         free_nullsafe(ctx, passwd);
00858                         free_nullsafe(ctx, chkpwd);
00859                         fprintf(stderr, "%s: Password is too short\n", MODULE);
00860                         return 1;
00861                 }
00862 
00863                 get_console_input(chkpwd, 64, "Verify password for user:", 1);
00864                 if( strcmp(passwd, chkpwd) != 0 ) {
00865                         free_nullsafe(ctx, passwd);
00866                         free_nullsafe(ctx, chkpwd);
00867                         fprintf(stderr, "%s: Passwords didn't match\n", MODULE);
00868                         return 1;
00869                 }
00870                 free_nullsafe(ctx, chkpwd);
00871         }
00872 
00873         // Prepare add user XML document with fieldMapping
00874         eurephiaXML_CreateDoc(ctx, 1, "UserAccount", &user_xml, &node);
00875         xmlNewProp(node, (xmlChar *) "mode", (xmlChar *) "add");
00876 
00877         node = xmlNewChild(node, NULL, (xmlChar *) "fieldMapping", NULL);
00878         xmlNewProp(node, (xmlChar *) "table", (xmlChar *) "users");
00879 
00880         xmlNewChild(node, NULL, (xmlChar *) "username", (xmlChar *) uname);
00881         node2 = xmlNewChild(node, NULL, (xmlChar *) "password", (xmlChar *) passwd);
00882         xmlNewProp(node2, (xmlChar *) "pwhash", (xmlChar *) "none");
00883 
00884         // Add the user
00885         resxml = eDBadminUserAccount(ctx, user_xml);
00886         xmlFreeDoc(user_xml);
00887         memset(passwd, 0, strlen_nullsafe(passwd));
00888         free_nullsafe(ctx, passwd);
00889         if( (resxml == NULL) || !eurephiaXML_IsResultMsg(ctx, resxml) ) {
00890                 fprintf(stderr, "%s: Failed to register the user.  Unknown failure.\n", MODULE);
00891                 return 1;
00892         }
00893 
00894         res = eurephiaXML_ParseResultMsg(ctx, resxml);
00895         if( res == NULL ) {
00896                 fprintf(stderr, "%s: Failed to register the user.  No results returned.\n", MODULE);
00897                 xmlFreeDoc(resxml);
00898                 return 1;
00899         } else if( res->resultType == exmlERROR ) {
00900                 fprintf(stderr, "%s: %s\n", MODULE, res->message);
00901                 xmlFreeDoc(resxml);
00902                 free_nullsafe(ctx, res);
00903                 return 1;
00904         }
00905 
00906         if( xmlStrcmp(res->details->children->name, (xmlChar *) "UserAccount") != 0 ) {
00907                 fprintf(stderr, "%s: Invalid result value.  User account might be registered\n", MODULE);
00908                 xmlFreeDoc(resxml);
00909                 free_nullsafe(ctx, res);
00910                 return 1;
00911         }
00912 
00913         fprintf(stdout, "%s: %s\n", MODULE, res->message);
00914         uid = atoi_nullsafe(xmlGetAttrValue(res->details->properties, "uid"));
00915         xmlFreeDoc(resxml);
00916         free_nullsafe(ctx, res);
00917 
00918         if( (digest != NULL) || (certfile != NULL) ) {
00919                 if( digest != NULL ) {
00920                         xmlDoc *cert_xml = NULL, *certlist = NULL;
00921                         xmlNode *cert_n = NULL;
00922                         int certcount = 0;
00923 
00924                         // when we have certificate digest, look that up
00925                         eurephiaXML_CreateDoc(ctx, 1, "certificates", &cert_xml, &cert_n);
00926                         assert( (cert_xml != NULL) && (cert_n != NULL) );
00927                         xmlNewProp(cert_n, (xmlChar *) "mode", (xmlChar *) "list");
00928                         xmlNewChild(cert_n, NULL, (xmlChar *) "sortkeys", (xmlChar *) "certid");
00929 
00930                         cert_n = xmlNewChild(cert_n, NULL, (xmlChar *) "fieldMapping", NULL);
00931                         xmlNewProp(cert_n, (xmlChar *) "table", (xmlChar *) "certificates");
00932                         xmlNewChild(cert_n, NULL, (xmlChar *) "digest", (xmlChar *) digest);
00933 
00934                         certlist = eDBadminCertificate(ctx, cert_xml);
00935                         if( certlist == NULL ) {
00936                                 fprintf(stderr, "%s: Error while looking up certificate info.\n"
00937                                         "%s: User account is not associated with any certificates\n",
00938                                         MODULE, MODULE);
00939                                 xmlFreeDoc(cert_xml);
00940                                 goto exit;
00941                         }
00942                         xmlFreeDoc(cert_xml);
00943 
00944                         cert_n = eurephiaXML_getRoot(ctx, certlist, "certificates", 1);
00945                         if( cert_n == NULL ) {
00946                                 fprintf(stderr, "%s: Could not find certificates root node in XML document. "
00947                                         "No association done.\n", MODULE);
00948                                 xmlFreeDoc(certlist);
00949                                 goto exit;
00950                         }
00951                         certcount = atoi_nullsafe(xmlGetAttrValue(cert_n->properties, "certificates"));
00952                         if( certcount == 0) {
00953                                 fprintf(stderr, "%s: No certificates was found. No association is done.\n",
00954                                         MODULE);
00955                                 xmlFreeDoc(certlist);
00956                                 goto exit;
00957                         } else if( certcount > 1 ) {
00958                                 fprintf(stderr, "%s: More than one certificates was found. "
00959                                         "No association is done.\n", MODULE);
00960                                 xmlFreeDoc(certlist);
00961                                 goto exit;
00962                         }
00963 
00964                         // Get the first and only certificate node
00965                         cert_n = xmlFindNode(cert_n, "certificate");
00966                         if( cert_n == NULL ) {
00967                                 fprintf(stderr, "%s: Could not find certificate node in XML document. "
00968                                         "No association done.\n", MODULE);
00969                                 xmlFreeDoc(certlist);
00970                                 goto exit;
00971                         }
00972                         // finally, we should have located the certid in the XML
00973                         certid = atoi_nullsafe(xmlGetAttrValue(cert_n->properties, "certid"));
00974                         xmlFreeDoc(certlist);
00975                 } else if( certfile != NULL ) {
00976                         // when we have certfile - register the certificate and register the link
00977                         certinfo *ci = NULL;
00978 
00979                         ci = Cert_ParseFile(certfile, certfile_format);
00980                         if( ci == NULL ) {
00981                                 fprintf(stderr, "%s: Could not parse the certificate file.  "
00982                                         "No association done.\n", MODULE);
00983                                 goto exit;
00984                         }
00985 
00986                         certid = register_certificate(ctx, 0, ci->digest, ci->common_name, ci->org, ci->email);
00987                         if( certid == 0 ) {
00988                                 fprintf(stderr, "%s: Failed to register certificate file.  No association done.",
00989                                         MODULE);
00990                         }
00991                 }
00992         }
00993 
00994         // If we have a certificate id, register a certificate link to the user account
00995         if( (certid > 0) && (uid > 0) ) {
00996                 xmlDoc *usercert_xml = NULL, *res_xml = NULL;
00997                 xmlNode *usercert_n = NULL;
00998                 eurephiaRESULT *res = NULL;
00999                 xmlChar tmp[66];
01000 
01001                 memset(&tmp, 0, 66);
01002                 eurephiaXML_CreateDoc(ctx, 1, "usercerts", &usercert_xml, &usercert_n);
01003                 assert( (usercert_xml != NULL) && (usercert_n != NULL) );
01004 
01005                 xmlNewProp(usercert_n, (xmlChar *) "mode", (xmlChar *) "register");
01006                 usercert_n = xmlNewChild(usercert_n, NULL, (xmlChar *) "fieldMapping", NULL);
01007                 xmlNewProp(usercert_n, (xmlChar *) "table", (xmlChar *) "usercerts");
01008 
01009                 xmlStrPrintf(tmp, 64, (xmlChar *) "%i%c", uid, '\0');
01010                 xmlNewChild(usercert_n, NULL, (xmlChar *) "uid", tmp);
01011                 xmlStrPrintf(tmp, 64, (xmlChar *) "%i%c", certid, '\0');
01012                 xmlNewChild(usercert_n, NULL, (xmlChar *) "certid", tmp);
01013 
01014                 res_xml = eDBadminUserCertsLink(ctx, usercert_xml);
01015                 if( res_xml == NULL ) {
01016                         fprintf(stderr, "%s: Failed to register user <-> certificate link\n", MODULE);
01017                         goto exit;
01018                 }
01019 
01020                 res = eurephiaXML_ParseResultMsg(ctx, res_xml);
01021                 if( res == NULL ) {
01022                         fprintf(stderr, "%s: Failed to register user <-> certificate link.  "
01023                                 "No results received\n", MODULE);
01024                 } else if( res->resultType == exmlERROR ) {
01025                         fprintf(stderr, "%s: %s\n", MODULE, res->message);
01026                 }
01027                 free_nullsafe(ctx, res);
01028                 xmlFreeDoc(res_xml);
01029         }
01030  exit:
01031         return (uid > 0);
01032 }
01033 
01034 
01046 int cmd_Users(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) {
01047         char **mode_argv;
01048         int i, mode_argc = 0, rc = 0;
01049         int (*mode_fnc) (eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv);
01050 
01051         e_options modeargs[] = {
01052                 {"--list", "-l", 0},
01053                 {"--show", "-s", 0},
01054                 {"--activate", "-a", 0},
01055                 {"--deactivate", "-d", 0},
01056                 {"--add", "-A", 0},
01057                 {"--delete", "-D", 0},
01058                 {"--password", "-p", 0},
01059                 {"--help", "-h", 0},
01060                 {NULL, NULL, 0}
01061         };
01062 
01063         assert((ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL));
01064         mode_fnc = NULL;
01065         for( i = 1; i < argc; i++ ) {
01066                 switch( eurephia_getopt(&i, argc, argv, modeargs) ) {
01067                 case 'l':
01068                         mode_fnc = list_users;
01069                         break;
01070 
01071                 case 's':
01072                         mode_fnc = show_user;
01073                         break;
01074 
01075                 case 'a':
01076                         mode_fnc = account_activation;
01077                         break;
01078 
01079                 case 'd':
01080                         mode_fnc = account_activation;
01081                         break;
01082 
01083                 case 'h':
01084                         mode_fnc = help_Users2;
01085                         break;
01086 
01087                 case 'A':
01088                         mode_fnc = add_user;
01089                         break;
01090 
01091                 case 'D':
01092                         mode_fnc = account_activation;
01093                         break;
01094 
01095                 case 'p':
01096                         mode_fnc = account_activation;
01097                         break;
01098 
01099                 default:
01100                         break;
01101                 }
01102                 if( mode_fnc != NULL ) {
01103                         break;
01104                 }
01105         }
01106 
01107         // If we do not have any known mode defined, exit with error
01108         if( mode_fnc == NULL )  {
01109                 fprintf(stderr, "Unknown argument.  No mode given\n");
01110                 return 1;
01111         }
01112 
01113         // Allocate memory for our arguments being sent to the mode function
01114         mode_argv = (char **) calloc(sizeof(char *), (argc - i)+2);
01115         assert(mode_argv != NULL);
01116 
01117         // Copy over only the arguments needed for the mode
01118         mode_argc = eurephia_arraycp(i, argc, argv, mode_argv, (argc - i));
01119 
01120         // Call the mode function
01121         rc = mode_fnc(ctx, sess, cfg, mode_argc, mode_argv);
01122         free_nullsafe(ctx, mode_argv);
01123 
01124         return rc;
01125 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines