/* usercerts.c -- eurephiadm usercerts command: * Management of user account <-> certificate links * * GPLv2 only - Copyright (C) 2008 - 2010 * 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. * */ /** * @file eurephiadm/commands/usercerts.c * @author David Sommerseth * @date 2008-12-28 * * @brief eurephiadm usercerts command. Manages the user account and certificate links. * */ #include #include #include #ifdef HAVE_LIBXML2 #include #include #endif #define MODULE "eurephia::UserCerts" /**< Need to define the current module before including argparser.h */ #include #include #include #include #include #include #include #include #include #include "../argparser.h" #include "../xsltparser.h" /** * Help screens for the usercerts command * * @param page which help screen to display */ void display_usercerts_help(int page) { switch( page ) { case 'A': printf("The add mode will register a new link between a user account and a certificate.\n" "\n" " -c | --certid Required - Certificate ID\n" " -i | --uid Required - User account ID\n" #ifdef FIREWALL " -a | --accessprofile Firewall profile ID to use for this access\n" #endif "\n" ); break; case 'D': printf("The delete mode will delete a link between a user account and a certificate.\n" "\n" " -c | --certid Certificate ID\n" " -i | --uid User account ID\n" " -n | --uicid Unique record id of certificate and user account link\n" #ifdef FIREWALL " -a | --accessprofile Firewall profile ID\n" #endif "\n" ); break; case 'l': printf("The list mode will list all registered links between user accounts and certificates.\n" "\n" "Options:\n" " -S | --sort Define the sorting of the list\n" "\n" ); break; #ifdef FIREWALL case 'S': printf("The set-fwprofile mode will update the firewall access profile for " "a given user-cert link\n\n" "Options: (both required)\n" " -n | --uicid Unique record id of certificate and user account link\n" " -a | --accessprofile Firewall profile ID\n" "\n"); break; #endif default: printf("Available modes for the usercerts command are:\n\n" " -A | --add Register a new certificate and user-cert link\n" " -D | --delete Delete a certificate and user-cert link\n" #ifdef FIREWALL " -S | --set-fwprofile Sets the firewall access profile for a user-cert link \n" #endif " -l | --list List all registered user-cert links\n" " -h | --help Help about a specific mode\n\n"); break; } } /** * Help screen wrapper. Used by cmd_Help() */ void help_UserCerts() { display_usercerts_help(0); } /** * Help screen wrapper for the usercerts help function. * * @param ctx eurephiaCTX * @param sess eurephiaSESSION of the current logged in user * @param cfg eurephiaVALUES struct of the current configuration * @param argc argument count for the eurephiadm command * @param argv argument table for the eurephiadm command * * @return returns 0 on success, otherwise 1. */ int help_UserCerts2(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { e_options helpargs[] = { {"--list", "-l", 0}, {"--add", "-A", 0}, {"--delete", "-D", 0}, #ifdef FIREWALL {"--set-fwprofile", "-S", 0}, #endif {NULL, NULL, 0} }; int i = 1; display_usercerts_help(eurephia_getopt(&i, argc, argv, helpargs)); return 0; } /** * usercerts list mode. Lists all registered user account and certificate links. * * @param ctx eurephiaCTX * @param sess eurephiaSESSION of the current logged in user * @param cfg eurephiaVALUES struct of the current configuration * @param argc argument count for the eurephiadm command * @param argv argument table for the eurephiadm command * * @return returns 0 on success, otherwise 1. */ int list_usercerts(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { xmlDoc *list_xml = NULL, *srch_xml = NULL; xmlNode *srch_n = NULL, *fmap_n = NULL; int i = 0; #ifdef FIREWALL const char *xsltparams[] = { "firewall", "'1'", NULL}; #else const char *xsltparams[] = { "firewall", "'0'", NULL}; #endif e_options listargs[] = { {"--sort", "-S", 1}, {"--help", "-h", 0}, {NULL, NULL, 0} }; assert( (ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL)); eurephiaXML_CreateDoc(ctx, 1, "usercerts", &srch_xml, &srch_n); assert( srch_xml != NULL && srch_n != NULL ); xmlNewProp(srch_n, (xmlChar *) "mode", (xmlChar *) "search"); fmap_n = xmlNewChild(srch_n, NULL, (xmlChar *) "fieldMapping", NULL); xmlNewProp(fmap_n, (xmlChar *) "table", (xmlChar *) "usercerts"); // Parse arguments for( i = 1; i < argc; i++ ) { switch( eurephia_getopt(&i, argc, argv, listargs) ) { case 'S': xmlNewChild(srch_n, NULL, (xmlChar *) "sortfields", (xmlChar *)optargs[0]); break; case 'h': display_usercerts_help('l'); return 0; default: return 1; } } list_xml = eDBadminUserCertsLink(ctx, srch_xml); if( list_xml == NULL ) { fprintf(stderr, "%s: Error retrieving user/certificate link list\n", MODULE); return 1; } xslt_print_xmldoc(stdout, cfg, list_xml, "usercerts.xsl", xsltparams); xmlFreeDoc(list_xml); return 0; } /** * usercerts add and delete mode. Modifies the user-certs links. * * @param ctx eurephiaCTX * @param sess eurephiaSESSION of the current logged in user * @param cfg eurephiaVALUES struct of the current configuration * @param argc argument count for the eurephiadm command * @param argv argument table for the eurephiadm command * * @return returns 0 on success, otherwise 1. */ int add_del_usercert(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { xmlDoc *usercert_xml = NULL, *resxml = NULL; xmlNode *usercert_n = NULL; eurephiaRESULT *res = NULL; int i = 0, rc = 0, actmode = 0; char *certid = NULL, *uid = NULL, *uicid = NULL, *actmode_str = NULL, *accessprofile = NULL; e_options addargs[] = { {"--uid", "-i", 1}, {"--certid", "-c", 1}, {"--uicid", "-n", 1}, #ifdef FIREWALL {"--accessprofile", "-a", 1}, #endif {"--help", "-h", 0}, {NULL, NULL, 0} }; assert( (ctx != NULL) && (ctx->dbc != NULL) && (ctx->dbc->config != NULL)); if( (strcmp(argv[0], "--add") == 0) || (strcmp(argv[0], "-A") == 0) ) { actmode = 'A'; actmode_str = "registered"; } else if( (strcmp(argv[0], "--delete") == 0) || (strcmp(argv[0], "-D") == 0) ) { actmode = 'D'; actmode_str = "deleted"; } eurephiaXML_CreateDoc(ctx, 1, "usercerts", &usercert_xml, &usercert_n); assert( (usercert_xml != NULL) && (usercert_n != NULL) ); xmlNewProp(usercert_n, (xmlChar *) "mode", (xmlChar *) (actmode == 'D' ? "remove" : "register")); usercert_n = xmlNewChild(usercert_n, NULL, (xmlChar *) "fieldMapping", NULL); xmlNewProp(usercert_n, (xmlChar *) "table", (xmlChar *) "usercerts"); for( i = 1; i < argc; i++ ) { switch( eurephia_getopt(&i, argc, argv, addargs) ) { case 'i': if( atoi_nullsafe(optargs[0]) < 1 ) { fprintf(stderr, "%s: User ID must be a positive number (>0)\n", MODULE); rc = 1; goto exit; } xmlNewChild(usercert_n, NULL, (xmlChar *) "uid", (xmlChar *) optargs[0]); uid = optargs[0]; break; case 'c': if( atoi_nullsafe(optargs[0]) < 1 ) { fprintf(stderr,"%s: Certificate ID must be a positive number (>0)\n",MODULE); rc = 1; goto exit; } xmlNewChild(usercert_n, NULL, (xmlChar *) "certid", (xmlChar *) optargs[0]); certid = optargs[0]; break; #ifdef FIREWALL case 'a': if( atoi_nullsafe(optargs[0]) < 1 ) { fprintf(stderr, "%s: Firewall profile ID must be a positive number (>0)\n", MODULE); rc = 1; goto exit; } xmlNewChild(usercert_n, NULL, (xmlChar *) "accessprofile", (xmlChar *) optargs[0]); accessprofile = optargs[0]; break; #endif case 'n': if( actmode != 'D' ) { fprintf(stderr, "%s: --uicid cannot be used with --add\n", MODULE); rc = 1; goto exit; } if( atoi_nullsafe(optargs[0]) < 1 ) { fprintf(stderr, "%s: uicid must be a positive number (>0)\n", MODULE); rc = 1; goto exit; } xmlNewChild(usercert_n, NULL, (xmlChar *) "uicid", (xmlChar *) optargs[0]); uicid = optargs[0]; break; case 'h': display_usercerts_help(actmode); rc = 0; goto exit; default: rc = 1; goto exit; } } if( (actmode == 'A') && ((certid == NULL) || (uid == NULL)) ) { fprintf(stderr, "%s: You must provide both a user ID (--uid) and " "a certificate ID (--certid)\n", MODULE); rc = 1; goto exit; } if( (actmode == 'D') && (certid == NULL) && (uid == NULL) && (uicid == NULL) && (accessprofile == NULL)) { fprintf(stderr, "%s: You must provide at least --uid, --certid, " "--uicid or --accessprofile\n", MODULE); rc = 1; goto exit; } resxml = eDBadminUserCertsLink(ctx, usercert_xml); if( resxml == NULL ) { fprintf(stderr, "%s: Failed to update user <-> certificate link\n", MODULE); rc = 1; goto exit; } res = eurephiaXML_ParseResultMsg(ctx, resxml); if( res == NULL ) { fprintf(stderr, "%s: Failed to update user <-> certificate link. No result available.", MODULE); } else { if( res->resultType == exmlERROR ) { fprintf(stderr, "%s: %s\n", MODULE, res->message); rc = 1; } else { fprintf(stdout, "%s: %s\n", MODULE, res->message); rc = 0; } } free_nullsafe(ctx, res); xmlFreeDoc(resxml); exit: xmlFreeDoc(usercert_xml); return rc; } #ifdef FIREWALL /** * usercerts set-fwprofile mode. Changes the firewall profile for a specific user-certs link * * @param ctx eurephiaCTX * @param sess eurephiaSESSION of the current logged in user * @param cfg eurephiaVALUES struct of the current configuration * @param argc argument count for the eurephiadm command * @param argv argument table for the eurephiadm command * * @return returns 0 on success, otherwise 1. */ int set_fwprofile(eurephiaCTX *ctx, eurephiaSESSION *sess, eurephiaVALUES *cfg, int argc, char **argv) { xmlDoc *usercert_xml = NULL, *res_xml = NULL; xmlNode *usercert_n = NULL, *fmap_n = NULL; int rc = 0, i = 0; int accprf = 0, uicid = 0; e_options updateargs[] = { {"--uicid", "-n", 1}, {"--accessprofile", "-a", 1}, {"--help", "-h", 0}, {NULL, NULL, 0} }; // Setup a XML doc which contains information for the update eurephiaXML_CreateDoc(ctx, 1, "usercerts", &usercert_xml, &usercert_n); assert( (usercert_xml != NULL) && (usercert_n != NULL) ); xmlNewProp(usercert_n, (xmlChar *) "mode", (xmlChar *) "update"); fmap_n = xmlNewChild(usercert_n, NULL, (xmlChar *) "fieldMapping", NULL); xmlNewProp(fmap_n, (xmlChar *) "table", (xmlChar *) "usercerts"); // Parse arguments for( i = 1; i < argc; i++ ) { switch( eurephia_getopt(&i, argc, argv, updateargs) ) { case 'a': if( atoi_nullsafe(optargs[0]) < 1 ) { fprintf(stderr, "%s: Firewall profile ID must be a positive number (>0)\n", MODULE); rc = 1; goto exit; } xmlNewChild(fmap_n, NULL, (xmlChar *) "accessprofile", (xmlChar *) optargs[0]); accprf = 1; // Access profile is set break; case 'n': // The uicid value must not be used as a value in the tag, but // must be an uucid attribute in the tag. This is the // ID to the record we will update. uicid = atoi_nullsafe(optargs[0]); if( uicid < 1 ) { fprintf(stderr, "%s: uicid must be a positive number (>0)\n", MODULE); rc = 1; goto exit; } xmlNewProp(usercert_n, (xmlChar *) "uicid", (xmlChar *) optargs[0]); break; case 'h': display_usercerts_help('S'); rc = 0; goto exit; default: rc = 1; goto exit; } } if( (uicid < 1) || (accprf != 1) ) { fprintf(stderr, "%s: You must provide --uicid and --accessprofile\n", MODULE); rc = 1; goto exit; } res_xml = eDBadminUserCertsLink(ctx, usercert_xml); if( res_xml == NULL ) { fprintf(stderr, "%s: Failed to update firewall access profile for user-cert link\n", MODULE); rc = 1; goto exit; } else { eurephiaRESULT *res = eurephiaXML_ParseResultMsg(ctx, res_xml); if( res->resultType == exmlERROR ) { fprintf(stderr, "%s: %s\n", MODULE, res->message); rc = 1; } else { fprintf(stdout, "%s: %s\n", MODULE, res->message); rc = 0; } } xmlFreeDoc(res_xml); exit: xmlFreeDoc(usercert_xml); return rc; } #endif /** * Main function for the usercerts command. * * @param ctx eurephiaCTX * @param sess eurephiaSESSION of the current logged in user * @param cfg eurephiaVALUES struct of the current configuration * @param argc argument count for the eurephiadm command * @param argv argument table for the eurephiadm command * * @return returns 0 on success, otherwise 1. */ int cmd_UserCerts(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}, {"--add", "-A", 0}, {"--delete", "-D", 0}, #ifdef FIREWALL {"--set-fwprofile", "-S", 0}, #endif {"--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_usercerts; break; case 'h': mode_fnc = help_UserCerts2; break; case 'A': mode_fnc = add_del_usercert; break; case 'D': mode_fnc = add_del_usercert; break; #ifdef FIREWALL case 'S': mode_fnc = set_fwprofile; break; #endif 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, "%s: Unknown argument. No mode given\n", MODULE); 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(ctx, mode_argv); return rc; }