/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_cmds.c,v $ $Revision: 1.70.10.3 $ * $Source: /home/interpeak/CVSRoot/ipssh/src/ipssh_cmds.c,v $ * $Author: svc-cmnet $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Roger Boden ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 CONFIGURATION **************************************************************************** */ /* **************************************************************************** * 3 INCLUDE FILES **************************************************************************** */ #include "ipssh_h.h" #include "ipssh_config.h" #include "ipssh.h" #include "ipssh_sftp_clt.h" #include #include #include #include #include #include #include #include #include #include #include #include /* **************************************************************************** * 4 DEFINES **************************************************************************** */ #define IPSSH_SFTP_PROMPT "sftp> " #define IPSSH_SFTP_PW_PROMPT "Enter password: " /* **************************************************************************** * 5 TYPES **************************************************************************** */ /* **************************************************************************** * 6 EXTERN PROTOTYPES **************************************************************************** */ /* **************************************************************************** * 7 LOCAL PROTOTYPES **************************************************************************** */ IP_GLOBAL int ipssh_stop_cmd(int argc, char** argv); IP_GLOBAL int ipssh_list_cmd(int argc, char** argv); IP_GLOBAL int ipssh_keyfp_cmd(int argc, char** argv); IP_GLOBAL int ipssh_cmd_sftp(int argc, char** argv); /* **************************************************************************** * 8 DATA **************************************************************************** */ /* **************************************************************************** * 9 LOCAL FUNCTIONS **************************************************************************** */ #ifdef IPSSH_USE_SFTP_CLT_CMD /* *=========================================================================== * ipssh_cmd_sftp_sub_usage *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void ipssh_cmd_sftp_sub_usage(void) { ipcom_printf("cd path change remote directory"IP_LF); ipcom_printf("get remote-path [local-path] download file"IP_LF); ipcom_printf("put local-path [remote-path] upload file"IP_LF); ipcom_printf("pwd print remote working directory"IP_LF); ipcom_printf("ls remote directory listing"IP_LF); ipcom_printf("rename rename remote file/directory"IP_LF); ipcom_printf("rm path remove remote file"IP_LF); ipcom_printf("mkdir path create remote direcory"IP_LF); ipcom_printf("rmdir path remove remote directory"IP_LF); ipcom_printf("lcd path change local directory"IP_LF); ipcom_printf("lpwd print local working directory"IP_LF); ipcom_printf("lls local directory listing"IP_LF); ipcom_printf("lrm path remove local file"IP_LF); ipcom_printf("lmkdir path create local directory"IP_LF); ipcom_printf("lrmdir path remove local directory"IP_LF); ipcom_printf("quit quit sftp"IP_LF); ipcom_printf("exit quit sftp"IP_LF); } /* *=========================================================================== * ipssh_cmd_sftp_usage *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void ipssh_cmd_sftp_usage(void) { ipcom_printf("sftp [-p ] [-i ] [-f ] [-w ] -u "IP_LF); } #endif /* IPSSH_USE_SFTP_CLT_CMD */ #ifdef IPSSH_USE_KEY_FINGERPRINT /* *=========================================================================== * ipssh_keyfp_usage *=========================================================================== */ IP_STATIC void ipssh_keyfp_usage(void) { ipcom_printf("keyfp -f [-1] {-h|-b}"IP_LF); } #endif #ifdef IPSSH_USE_STOP_SPAWN /* *=========================================================================== * ipssh_stop_usage *=========================================================================== */ IP_STATIC void ipssh_stop_usage(void) { ipcom_printf("ipssh_stop [-a] [-c ] [-h]"IP_LF); ipcom_printf(" -a stop all logged in clients"IP_LF); ipcom_printf(" -c stop the logged in client with the specified id"IP_LF); ipcom_printf(" -h print usage information"IP_LF); } #endif /* *=========================================================================== * ipssh_list_usage *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void ipssh_list_usage(void) { ipcom_printf("ipssh_list [-lh]"IP_LF " -l print all info"IP_LF " -h print ipssh_list usage"IP_LF); } #ifdef IPSSH_USE_KEY_FINGERPRINT /* *=========================================================================== * ipssh_load_key *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC EVP_PKEY* ipssh_load_key(const char* file) { BIO* bio; EVP_PKEY* ret = IP_NULL; if(!file) return IP_NULL; bio = BIO_new(BIO_s_file()); if(!bio) { IPCOM_LOG0(ERR, "ipssh_load_key :: out of memory"); return IP_NULL; } if( !BIO_read_filename(bio, file) ) { IPCOM_LOG1(ERR, "ipssh_load_key :: failed to open %s", file); goto cleanup; } ret = PEM_read_bio_PrivateKey(bio, IP_NULL, IP_NULL, IP_NULL); if(!ret) { IPCOM_LOG1(ERR, "ipssh_load_key :: failed to load key from file: %s", file); } cleanup: if(bio) (void)BIO_free(bio); return ret; } #endif /* **************************************************************************** * 10 PUBLIC FUNCTIONS **************************************************************************** */ #ifdef IPSSH_USE_STOP_SPAWN /* *=========================================================================== * ipssh_stop_cmd *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL int ipssh_stop_cmd(int argc, char** argv) { Ipcom_getopt opt; int rc; Ip_pid_t pid; char* options = "hc:a"; if(argc == 1) { ipssh_stop_usage(); return IPCOM_ERR_FAILED; } ipcom_getopt_clear_r(&opt); while( (rc = ipcom_getopt_r(argc, argv, options, &opt)) != -1) { switch(rc) { case 'c': pid = (Ip_pid_t) ipcom_strtoul(opt.optarg, IP_NULL, 0); if(ipssh_stop_spawn(pid) != IPCOM_SUCCESS) { ipcom_printf("Failed to stop server"IP_LF); return IPCOM_ERR_FAILED; } break; case 'a': if(ipssh_stop_all_spawns() != IPCOM_SUCCESS) { ipcom_printf("Failed to stop spawned ipssh processes"IP_LF); return IPCOM_ERR_FAILED; } break; case '?': case 'h': ipssh_stop_usage(); return IPCOM_SUCCESS; default: IP_PANIC(); ipssh_stop_usage(); return IPCOM_ERR_FAILED; } } return IPCOM_SUCCESS; } #endif /* *=========================================================================== * ipssh_list_cmd *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL int ipssh_list_cmd(int argc, char** argv) { Ipcom_getopt opt; int rc; int print_all = 0; int pos = 0; Ipssh_clt_info clt_info; /* parse args */ ipcom_getopt_clear_r(&opt); while((rc = ipcom_getopt_r(argc, argv, "hl", &opt)) != -1) { switch(rc) { case 'l': print_all = 1; break; case '?': case 'h': ipssh_list_usage(); return IPCOM_SUCCESS; default: IP_PANIC(); } } if(ipssh_get_clt_info(&clt_info, pos) == IPCOM_SUCCESS) { ipcom_printf("Connected clients:"IP_LF); if(print_all) ipcom_printf("%-9s %-10s %-16s %-9s %-11s %-12s %-10s %s"IP_LF, "ID", "User", "Clt Addr", "Service", "Auth Meth", "Encr Alg", "MAC Alg", "Clt SW"); else ipcom_printf("%-9s %-10s %-16s %s"IP_LF, "ID", "User", "Clt Addr", "Service"); while(ipssh_get_clt_info(&clt_info, pos) == IPCOM_SUCCESS) { if(print_all) ipcom_printf("%-9d %-10s %-16s %-9s %-11s %-12s %-10s %s"IP_LF, clt_info.pid, clt_info.userid, clt_info.clt_addr, clt_info.service, clt_info.auth_method, clt_info.cipher, clt_info.mac, clt_info.ssh_clt_sw); else ipcom_printf("%-9d %-10s %-16s %s"IP_LF, clt_info.pid, clt_info.userid, clt_info.clt_addr, clt_info.service); pos++; } } else { ipcom_printf("No SSH clients connected"IP_LF); } return IPCOM_SUCCESS; } #ifdef IPSSH_USE_KEY_FINGERPRINT /* *=========================================================================== * ipssh_keyfp_cmd *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL int ipssh_keyfp_cmd(int argc, char** argv) { Ipcom_getopt opt; EVP_PKEY* key = IP_NULL; int rc; Ip_err ret_val = IPCOM_SUCCESS; char* finger_print = IP_NULL; int fp_type = 0; Ip_bool v1 = IP_FALSE; int key_type; if (argc < 3 || argc > 6) { ipssh_keyfp_usage(); return IPCOM_ERR_FAILED; } ipcom_getopt_clear_r(&opt); while((rc = ipcom_getopt_r(argc, argv, "f:hb1", &opt)) != -1) { switch(rc) { case 'f': key = ipssh_load_key(opt.optarg); break; case 'h': fp_type = IPSSH_HEX; break; case 'b': fp_type = IPSSH_BUBBLE_BABBLE; break; case '1': v1 = IP_TRUE; break; case '?': ipssh_keyfp_usage(); return IPCOM_SUCCESS; default: IP_PANIC(); } } if(key == IP_NULL) { ipcom_printf("Key file must be specified with -f " IP_LF); return IPCOM_ERR_FAILED; } if(!fp_type) { ipcom_printf("Key fingerprint type must be specified [-b|-h]" IP_LF); return IPCOM_ERR_FAILED; } if (v1) key_type = IPSSH_V1_RSA_ID; else key_type = key->type; if(ipssh_key_fingerprint2(key, key_type, &finger_print, fp_type) != IPCOM_SUCCESS) { ret_val =IPCOM_ERR_FAILED; #ifdef OPENSSL_FIPS if (FIPS_mode() && fp_type == IPSSH_HEX) ipcom_printf("Hex fingerprints not allowed in FIPS mode\n"); #endif ret_val = IPCOM_ERR_FAILED; ipcom_printf("Failed" IP_LF); goto cleanup; } ipcom_printf("%s" IP_LF, finger_print); cleanup: if(key) EVP_PKEY_free(key); if(finger_print) ipcom_free(finger_print); return ret_val; } #endif #ifdef IPSSH_USE_SFTP_CLT_CMD /* *=========================================================================== * ipssh_cmd_sftp *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL int ipssh_cmd_sftp(int argc, char** argv) { Ipssh_conn* ssh_conn = IP_NULL; Ipcom_getopt opt; int rc; int ret_val = IPCOM_ERR_FAILED; char* options = "hp:u:w:i:f:"; char* host; char* user = IP_NULL; char* pw = IP_NULL; int port = 22; char* key_file = IP_NULL; char* hostb_key_file = IP_NULL; char pw_buf[32]; Ipcom_getline* gl; BIO* bio = IP_NULL; int sftp_argc; char** sftp_argv = IP_NULL; if(argc == 1) { ipssh_cmd_sftp_usage(); return IPCOM_ERR_FAILED; } ipcom_getopt_clear_r(&opt); while( (rc = ipcom_getopt_r(argc, argv, options, &opt)) != -1) { switch(rc) { case 'p': port = ipcom_atoi(opt.optarg); if(port < 0 || port > 0xffff) { ipcom_printf("Invalid port"IP_LF); return IPCOM_ERR_FAILED; } break; case 'i': key_file = opt.optarg; break; case 'f': hostb_key_file = opt.optarg; break; case 'u': user = opt.optarg; break; case 'w': pw = opt.optarg; break; case 'h': ipssh_cmd_sftp_usage(); return IPCOM_SUCCESS; default: ipssh_cmd_sftp_usage(); return IPCOM_ERR_FAILED; } } if(opt.optind == argc - 1) host = argv[opt.optind]; else { ipcom_printf("No host given"IP_LF); return IPCOM_ERR_FAILED; } if(!user) { ipcom_printf("No user given"IP_LF); return IPCOM_ERR_FAILED; } gl = ipcom_getline_init(10); if(!gl) return IPCOM_ERR_FAILED; if(!pw && !key_file && !hostb_key_file) { ipcom_printf(IPSSH_SFTP_PW_PROMPT); (void)ipcom_fflush(ip_stdout); if(ipcom_getline(IP_INVALID_SOCKET, pw_buf, sizeof(pw_buf), IP_FALSE, gl, ipcom_strlen(IPSSH_SFTP_PW_PROMPT))) { ipcom_printf("Failed"IP_LF); goto cleanup; } ipcom_printf(IP_LF); (void)ipcom_fflush(ip_stdout); pw = pw_buf; } ssh_conn = ipssh_conn_new(); if(!ssh_conn) { ipcom_printf("ipssh_cmd_sftp :: out of memory"); goto cleanup; } (void)ipssh_sftp_clt_set_userid(ssh_conn, user); if(pw) (void)ipssh_sftp_clt_set_pw(ssh_conn, pw); if(key_file) { EVP_PKEY* key; bio = BIO_new(BIO_s_file()); if(!bio) { ipcom_printf("out of memory"IP_LF); goto cleanup; } if(!BIO_read_filename(bio, key_file)) { ipcom_printf("Failed to open key file: %s"IP_LF, key_file); goto cleanup; } key = PEM_read_bio_PrivateKey(bio, IP_NULL, IP_NULL, IP_NULL); if(!key) { ipcom_printf("Failed to read key from file: %s"IP_LF, key_file); goto cleanup; } if (ipssh_sftp_clt_set_key(ssh_conn, key) != IPCOM_SUCCESS) { ipcom_printf("Invalid key type in %s"IP_LF, key_file); EVP_PKEY_free(key); goto cleanup; } EVP_PKEY_free(key); } if (hostb_key_file) { EVP_PKEY* key; bio = BIO_new(BIO_s_file()); if(!bio) { ipcom_printf("out of memory"IP_LF); goto cleanup; } if(!BIO_read_filename(bio, hostb_key_file)) { ipcom_printf("Failed to open key file: %s"IP_LF, hostb_key_file); goto cleanup; } key = PEM_read_bio_PrivateKey(bio, IP_NULL, IP_NULL, IP_NULL); if(!key) { ipcom_printf("Failed to read key from file: %s"IP_LF, hostb_key_file); goto cleanup; } if (ipssh_sftp_clt_set_hostb_key(ssh_conn, key) != IPCOM_SUCCESS) { ipcom_printf("Invalid key type in %s"IP_LF, hostb_key_file); EVP_PKEY_free(key); goto cleanup; } EVP_PKEY_free(key); } if(ipssh_sftp_clt_open(ssh_conn, host, (Ip_u16)port) != IPCOM_SUCCESS) { ipcom_printf("Connection failed"IP_LF); goto cleanup; } while(1) { char sftp_cmd[64]; if(sftp_argv) { ipcom_free(sftp_argv); sftp_argv = IP_NULL; } ipcom_printf(IPSSH_SFTP_PROMPT); (void)ipcom_fflush(ip_stdout); if(ipcom_getline(IP_INVALID_SOCKET, sftp_cmd, sizeof(sftp_cmd), IP_TRUE, gl, ipcom_strlen(IPSSH_SFTP_PROMPT))) { ipcom_printf("Failed"IP_LF); goto cleanup; } if(ipcom_parse_argstr(sftp_cmd, &sftp_argc, &sftp_argv) != IPCOM_SUCCESS) { ipcom_printf("Failed 2"IP_LF); goto cleanup; } if(sftp_argc == 0) { continue; } if(ipcom_strcmp(sftp_argv[0], "get") == 0) { char* dst_file; if(sftp_argc < 2 || sftp_argc > 3) { ipcom_printf("Bad args"IP_LF); continue; } if(sftp_argc == 2) dst_file = sftp_argv[1]; else dst_file = sftp_argv[2]; if(ipssh_sftp_clt_get(ssh_conn, sftp_argv[1], dst_file) != IPCOM_SUCCESS) { ipcom_printf("Failed to get file"IP_LF); } continue; } if(ipcom_strcmp(sftp_argv[0], "put") == 0) { char* dst_file; int append_mode = 0; if(sftp_argc < 2 || sftp_argc > 4 || (ipcom_strcmp(sftp_argv[1], "-a")==0 && sftp_argc == 2)) { ipcom_printf("Bad args"IP_LF); continue; } if (ipcom_strcmp(sftp_argv[1], "-a") == 0) append_mode = 1; if(sftp_argc == 2 + append_mode) dst_file = sftp_argv[1+append_mode]; else dst_file = sftp_argv[2+append_mode]; if (append_mode) { if(ipssh_sftp_clt_put_flags(ssh_conn, sftp_argv[2], dst_file, IPSSH_FXF_WRITE|IPSSH_FXF_APPEND) != IPCOM_SUCCESS) { ipcom_printf("Failed to put file"IP_LF); } } else { if(ipssh_sftp_clt_put(ssh_conn, sftp_argv[1], dst_file) != IPCOM_SUCCESS) { ipcom_printf("Failed to put file"IP_LF); } } continue; } if(ipcom_strcmp(sftp_argv[0], "pwd") == 0) { char cwd[128]; if(sftp_argc != 1) { ipcom_printf("Bad args"IP_LF); continue; } if(ipssh_sftp_clt_get_cwd(ssh_conn, cwd, sizeof(cwd)) == IPCOM_SUCCESS) ipcom_printf("%s"IP_LF, cwd); else ipcom_printf("Failed"IP_LF); continue; } if(ipcom_strcmp(sftp_argv[0], "cd") == 0) { if(sftp_argc != 2) { ipcom_printf("Bad args"IP_LF); continue; } if(ipssh_sftp_clt_chdir(ssh_conn, sftp_argv[1]) != IPCOM_SUCCESS) ipcom_printf("Failed"IP_LF); continue; } if(ipcom_strcmp(sftp_argv[0], "ls") == 0) { char* path; void* handle; Ipssh_dirent* dir_entry; if( sftp_argc > 2) { ipcom_printf("Bad args"IP_LF); continue; } if(sftp_argc == 2) path = sftp_argv[1]; else path = "."; handle = ipssh_sftp_clt_opendir(ssh_conn, path); if(!handle) { ipcom_printf("Failed"IP_LF); continue; } while((dir_entry=ipssh_sftp_clt_readdir(ssh_conn, handle)) != IP_NULL) ipcom_printf("%s"IP_LF, dir_entry->longname); (void)ipssh_sftp_clt_closedir(ssh_conn, handle); continue; } if(ipcom_strcmp(sftp_argv[0], "rm") == 0) { if(sftp_argc != 2) { ipcom_printf("Bad args"IP_LF); continue; } if(ipssh_sftp_clt_unlink(ssh_conn, sftp_argv[1])) { ipcom_printf("Failed"IP_LF); } continue; } if(ipcom_strcmp(sftp_argv[0], "mkdir") == 0) { if(sftp_argc != 2) { ipcom_printf("Bad args"IP_LF); continue; } if(ipssh_sftp_clt_mkdir(ssh_conn, sftp_argv[1], 0744)) { ipcom_printf("Failed"IP_LF); } continue; } if(ipcom_strcmp(sftp_argv[0], "rename") == 0) { if(sftp_argc != 3) { ipcom_printf("Bad args"IP_LF); continue; } if(ipssh_sftp_clt_rename(ssh_conn, sftp_argv[1], sftp_argv[2])) { ipcom_printf("Failed"IP_LF); } continue; } if(ipcom_strcmp(sftp_argv[0], "rmdir") == 0) { if(sftp_argc != 2) { ipcom_printf("Bad args"IP_LF); continue; } if(ipssh_sftp_clt_rmdir(ssh_conn, sftp_argv[1])) { ipcom_printf("Failed"IP_LF); } continue; } if(ipcom_strcmp(sftp_argv[0], "help") == 0 || ipcom_strcmp(sftp_argv[0], "?") == 0) { ipssh_cmd_sftp_sub_usage(); continue; } /* Operations on local file system */ if(ipcom_strcmp(sftp_argv[0], "lcd") == 0) { if(ipcom_cmd_cd(sftp_argc, sftp_argv)) { ipcom_printf("Failed"IP_LF); } continue; } if(ipcom_strcmp(sftp_argv[0], "lpwd") == 0) { if(ipcom_cmd_pwd(sftp_argc, sftp_argv)) { ipcom_printf("Failed"IP_LF); } continue; } if(ipcom_strcmp(sftp_argv[0], "lls") == 0) { if(ipcom_cmd_ls(sftp_argc, sftp_argv)) { ipcom_printf("Failed"IP_LF); } continue; } if(ipcom_strcmp(sftp_argv[0], "lrm") == 0) { if(ipcom_cmd_rm(sftp_argc, sftp_argv)) { ipcom_printf("Failed"IP_LF); } continue; } if(ipcom_strcmp(sftp_argv[0], "lmkdir") == 0) { if(ipcom_cmd_mkdir(sftp_argc, sftp_argv)) { ipcom_printf("Failed"IP_LF); } continue; } if(ipcom_strcmp(sftp_argv[0], "lrmdir") == 0) { if(ipcom_cmd_rmdir(sftp_argc, sftp_argv)) { ipcom_printf("Failed"IP_LF); } continue; } if(ipcom_strcmp(sftp_argv[0], "quit") == 0 || ipcom_strcmp(sftp_argv[0], "exit") == 0) { break; } ipcom_printf("Unknown command: %s"IP_LF, sftp_argv[0]); } ret_val = IPCOM_SUCCESS; cleanup: if(ssh_conn) (void)ipssh_sftp_clt_close(ssh_conn); if(gl) ipcom_getline_exit(gl); if(bio) (void)BIO_free(bio); if(sftp_argv) ipcom_free(sftp_argv); return ret_val; } #endif /* IPSSH_USE_SFTP_CLT_CMD */ /* **************************************************************************** * END OF FILE **************************************************************************** */