/* ****************************************************************************** * IPSSH CONFIGURATION FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipssh_example.c,v $ $Revision: 1.10.10.12 $ * $Source: /home/interpeak/CVSRoot/ipssh/config/ipssh_example.c,v $ * $Author: jren $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * Design and implementation by Roger Boden ****************************************************************************** */ /* **************************************************************************** * 1 DESCRIPTION **************************************************************************** */ /* **************************************************************************** * 2 INCLUDE FILES **************************************************************************** */ #define IPCOM_USE_CLIB_PROTO #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef IPCOM_USE_AUTH #include #endif #include #include "ipssh_config.h" #include #include #ifdef IPSSH_USE_RSA #include #endif #include #include #include #include /* **************************************************************************** * 3 DEFINES **************************************************************************** */ #define IPCOM_SYSLOG_FACILITY IPCOM_LOG_IPSSH #define IPCOM_SYSLOG_PRIORITY IPSSH_SYSLOG_PRIORITY /* Defines used in ipssh_sftp_check_access_cb */ #define IPSSH_FXP_OPEN 3 #define IPSSH_FXP_REMOVE 13 #define IPSSH_FXP_MKDIR 14 #define IPSSH_FXP_RMDIR 15 #define IPSSH_FXF_READ 0x00000001 #define IPSSH_FXF_WRITE 0x00000002 #define IPSSH_FXF_APPEND 0x00000004 #define IPSSH_FXF_CREAT 0x00000008 #define IPSSH_FXF_TRUNC 0x00000010 #define IPSSH_FXF_EXCL 0x00000020 /* The following values are defined by Wind River */ #define IPSSH_FXP_ACCESS 254 #define IPSSH_FXP_MAX 255 /* Defines the SUBDIR under IPCOM_FILE_ROOT to be used for hostbased authentication */ #define IPSSH_HOSTBASED_SUBDIR "host_based/" #define IPSSH_HOSTBASED_HOSTS "hosts" #define IPSSH_ALL_MATCH '+' #define IPSSH_FILE_LINE_MAX 256 /* **************************************************************************** * 4 TYPES **************************************************************************** */ /* **************************************************************************** * 5 EXTERN PROTOTYPES **************************************************************************** */ IP_GLOBAL EVP_PKEY *ipssh_buffer_get_pub_key(Ipcom_buffer *buf); /* **************************************************************************** * 6 LOCAL PROTOTYPES **************************************************************************** */ IP_PUBLIC Ipssh_sftp_func_cb * ipssh_get_sftp_func_example_cb(const char *path); IP_PUBLIC Ip_err ipssh_sftp_check_access_example_cb(const char *user, int action, const char *path, int flags); IP_PUBLIC Ip_err ipssh_shell_check_access_example_cb(const char *user, int flags); IP_PUBLIC RSA* ipssh_load_rsa_key_example_cb(void); IP_PUBLIC DSA* ipssh_load_dsa_key_example_cb(void); IP_PUBLIC RSA* ipssh_load_rsa_keyex_key_example_cb(void); IP_PUBLIC Ip_err ipssh_validate_userid_pw_example_cb(const char *user, const char *pw, Ipcom_shell_ctx* sh_ctx); IP_PUBLIC Ip_err ipssh_validate_pubkey_example_cb(const char *user, EVP_PKEY *pub_key, Ipcom_shell_ctx* sh_ctx); IP_PUBLIC Ip_err ipssh_validate_hostbased_example_cb(const char *user, char *host, EVP_PKEY *pub_key, Ipcom_shell_ctx* sh_ctx); IP_PUBLIC RSA* ipssh_validate_rsa_pubkey_v1_example_cb(const char *user, BIGNUM *modulus, Ipcom_shell_ctx* sh_ctx); IP_PUBLIC Ip_err ipssh_auth_complete_example_cb(const char* user, Ipcom_shell_ctx* sh_ctx); IP_PUBLIC Ip_err ipssh_validate_srv_public_key_example_cb(EVP_PKEY *srv_key, const union Ip_sockaddr_union *srv_addr); /* **************************************************************************** * 7 DATA **************************************************************************** */ const char* ipssh_config_moduli[] = { "# Time Type Tests Tries Size Generator Modulus\n", "20091127121438 2 6 100 1023 2 DED9746EEB7B4D109990192834993E729FCF5AEBDCA387C70889950CEE69DF4BEFE932148B03DCEE83CDCA436B6952FCA1C42F33C7A080101A58B8C72A29B98F0D81F99936456CB896FBC0383D5685673A491EDCA2FDF8D9A66ADA0826F11DF6500E4F3C5EC679CAFCF26D29E67B773400AB0B41BE2DDEECBBE5FBBB924FFA9B\n", "20091127121441 2 6 100 1023 5 DED9746EEB7B4D109990192834993E729FCF5AEBDCA387C70889950CEE69DF4BEFE932148B03DCEE83CDCA436B6952FCA1C42F33C7A080101A58B8C72A29B98F0D81F99936456CB896FBC0383D5685673A491EDCA2FDF8D9A66ADA0826F11DF6500E4F3C5EC679CAFCF26D29E67B773400AB0B41BE2DDEECBBE5FBBB925D65D7\n", "20091127121606 2 6 100 1535 2 FFB42147DDA1DA06A6A8D93D186841B394B7A77C025FFC79EB53DBC9BF5629FDFB87568351596F190BDD99B4FAA3BD8AA5F45C0343F0F90ADECF83C86966C66FB587459B4DC0D072CC5ACB8B84921B0E2458BF33019D1CCBED8329B7E4A938F85F874581399C45534E534B6F7A423520C0120AED227992C55644B28C342C473EA91C22A6C25E2DDA7C02A7FBDE241821955E2FBCEAAA1CEBD620E4390E9FAF966BF36D7B665DDDC0DDB0788B04D27F743022AAF7CB2BC47DC09D326F183B4C9B\n", "20091127121804 2 6 100 1535 5 FFB42147DDA1DA06A6A8D93D186841B394B7A77C025FFC79EB53DBC9BF5629FDFB87568351596F190BDD99B4FAA3BD8AA5F45C0343F0F90ADECF83C86966C66FB587459B4DC0D072CC5ACB8B84921B0E2458BF33019D1CCBED8329B7E4A938F85F874581399C45534E534B6F7A423520C0120AED227992C55644B28C342C473EA91C22A6C25E2DDA7C02A7FBDE241821955E2FBCEAAA1CEBD620E4390E9FAF966BF36D7B665DDDC0DDB0788B04D27F743022AAF7CB2BC47DC09D326F193F12C7\n", "20091127121856 2 6 100 2047 2 FD13BF5CB5B2A2413BD26E2ED1C4C42397484E869C94DB07CED481DB2772F3F5749C11C1974E8936E8D5D6BA964C833632E2CC5C6223150E8763381EBA7D7D9559B0581FD24E9A49F979091874D5315BB44E8E4FD1E671FA96912C9E58D9BE5AEFC64DFB322B0F54A5DFF237CD1148429CC86E1F4F742828E5CEB6CEF6D8ADF590F74C972DCF945E7DD6ECC103820676ED58E7FC3214DD175E111AAC8887B3E976361B137EC7212D3BDE7A2DA3E664CA634034177641F3F5605A76D341FA9DECBEE859ABAEBB1326188CEAC3AA2C9E9D0943748C8EE29B57BF6C844DE01A05514BF8687F58B997476B7A75AC3EFDA8006BEB3AD48D5ECE34C125B92A8DB20873\n", "20091127121912 2 6 100 2047 5 FD13BF5CB5B2A2413BD26E2ED1C4C42397484E869C94DB07CED481DB2772F3F5749C11C1974E8936E8D5D6BA964C833632E2CC5C6223150E8763381EBA7D7D9559B0581FD24E9A49F979091874D5315BB44E8E4FD1E671FA96912C9E58D9BE5AEFC64DFB322B0F54A5DFF237CD1148429CC86E1F4F742828E5CEB6CEF6D8ADF590F74C972DCF945E7DD6ECC103820676ED58E7FC3214DD175E111AAC8887B3E976361B137EC7212D3BDE7A2DA3E664CA634034177641F3F5605A76D341FA9DECBEE859ABAEBB1326188CEAC3AA2C9E9D0943748C8EE29B57BF6C844DE01A05514BF8687F58B997476B7A75AC3EFDA8006BEB3AD48D5ECE34C125B92A8DBE435F\n", "20091127131246 2 6 100 3071 2 F4498C1311EB3380830CC2CEFE61A9FC5C8A48025930A8B5D1DB92D21C4140B5444E3B5CC212C0732B7B1D21CE5BAD4AC324E0A6C19D23604C1A95091878BE447F5F020D1567749FD125003BDBF3700E0F47CA0911246B1A10DCDFED8C39A1CF155E741B8DB986685EE383DC2DCA74B2A7DEE7DCDF42363F984F200DBAB76EB850285706EE7F7D34FBABA6C01DCDC518248BDC8D36C9376E13607419D07E50E43B7CBC36B423AA35126DE5C69B8F250041951953858F530BC8F889866E91B04ADA706AE38C88F2300F4A2BA780EB8B6D47FF698749127FE4D74885CF52155955B86E58D37BD8184F8D7EC19B59B5099C9C07EBCE87DAB14BA0E1DAA90E41367830ADD54FE5615419FABA3D835C2E35D700AC859A1A32B553604A385C1FD656B18CCD30C232BF075ADC919B075F6881F4067206DB08281A57C56CC85F3E1BDB764B123F5C2BAC387D674B5D1383288A5703DB309C21118FA886FF867E90A41D2A05232A1D22424B7E1A3EFE2E6F61B1CBE9F85F170EE76DD15FA320254BAB0C73\n", "20091127130507 2 6 100 4095 2 C9EB7179A90B0A373ECDF008C689CFBFFC2171AA9776EF7A0B14679F8BFB9BD53A0D846E83A5609A73F23229BEC6185D6BFCF5DBECB77A742E407DA9E734AD5F3D9DDB05C350B96FC6FEA930410AA06657984CC6018A44BC274E3D22CB969751D7E3D62CD94E6A7FBD9044097E1F63F7A3162F4AC9F32895756F2E5E60C2087A185C1A6F68877453D5CA0E31546F033427AE704CF09F19E164627C74B017577B9E9C75A7ADF02934388D4E8EC4FBA580040E5C6F499A391BB9D45894F9E4118573F33BBA5E0D8C4A897EE2F93DE22A104EFF1F746B7E475812252A7285EFC878C114D648FE534897C9498277CCDF29103043AA512F8634F673CFE8CA0B4C7CAB5531C4E76BA0AA596F65ABE658EE671F2901F6352039297C324192AF0944FD76247F501A0035012BE6AD971C7C1BC3452156B54E5C1F8089078D3BF0477686D7BDE475369CCD3DB1ADEC31C6F0ED432D5BB4FA553C152C4A6BF549CB44AB670BB4FBE49598D813986600C2ED78CE72F2F427A6F56FF80DA203D330BBA674AE192AB2DB44DBC2AA7D4660CC941C2A5C287939762AF46691BDB49817D1F58F8B512687890B7F3B79A692BAFFCEA9E1FA7E4823E12CC119C7A0F127C65FDF72085838A897531DABC649487037AB63CC415CA691EBE09128E5727A71F32CEA267008629B37EBC52CD05A7E11F20CE0E8EA0CBCA0630DDB428D0B4B1D346ABEA116EB\n", "20091127132635 2 6 100 4095 2 C9EB7179A90B0A373ECDF008C689CFBFFC2171AA9776EF7A0B14679F8BFB9BD53A0D846E83A5609A73F23229BEC6185D6BFCF5DBECB77A742E407DA9E734AD5F3D9DDB05C350B96FC6FEA930410AA06657984CC6018A44BC274E3D22CB969751D7E3D62CD94E6A7FBD9044097E1F63F7A3162F4AC9F32895756F2E5E60C2087A185C1A6F68877453D5CA0E31546F033427AE704CF09F19E164627C74B017577B9E9C75A7ADF02934388D4E8EC4FBA580040E5C6F499A391BB9D45894F9E4118573F33BBA5E0D8C4A897EE2F93DE22A104EFF1F746B7E475812252A7285EFC878C114D648FE534897C9498277CCDF29103043AA512F8634F673CFE8CA0B4C7CAB5531C4E76BA0AA596F65ABE658EE671F2901F6352039297C324192AF0944FD76247F501A0035012BE6AD971C7C1BC3452156B54E5C1F8089078D3BF0477686D7BDE475369CCD3DB1ADEC31C6F0ED432D5BB4FA553C152C4A6BF549CB44AB670BB4FBE49598D813986600C2ED78CE72F2F427A6F56FF80DA203D330BBA674AE192AB2DB44DBC2AA7D4660CC941C2A5C287939762AF46691BDB49817D1F58F8B512687890B7F3B79A692BAFFCEA9E1FA7E4823E12CC119C7A0F127C65FDF72085838A897531DABC649487037AB63CC415CA691EBE09128E5727A71F32CEA267008629B37EBC52CD05A7E11F20CE0E8EA0CBCA0630DDB428D0B4B1D346ABF93E1C3\n", "20091202164729 2 6 100 6143 5 CB063BF4EA7550A67C6DA351DB0D123315DDB7F231AD211F391BF56B048C51C41CCF7D731D575BEF44E234DAD302636D9BDA26C6530FB5889441E42F6307ACA68C726303BF0CBDD40FF1223F230F37F000C5E4691B75D25D7EF21BE7BDB106F7A4E0D6C8CB34280EAE6A0A368515B5B7A573B694F737EF5CE355F2D8332C4944735DABE1D2C9BED684186CCD88228CF9BAF27AC9F39954F65C0D2D72C95C54F9540B296A4931A8C7403B60A48217318F9B860143B99F41BD59CC1318E0F659F1E4D8AA36C1543E6FE7F481C581E9C4D45FEDAEBB4EA79997D6E3A5EA175CC7FE85E357A03582DC2CFC0B9861AB23C34D2E651AEBC0C3CA174F6897DED11757BD7D300D447A22E0BA730D78087E0E5564EDBD20AC8CD205FF7AF712CCF8FD4B687000F89F12775220043CB3477F7C64569FF87B6C55E15FC98CAA079D67A825B8696AC7104C063A4A007F385786E808E1DD5E3C8CCC7392F6D8C763CF0EA132C87552B7611B51EA166253763B31AD96EAAB957FEAABF9E70B5FA5CAFAE0DA363A756B29095F75A3B42B5601433AFA32AEB27C61CECCAE3C65742E9907FA1A8F801AA1E3D49E3C968324B950C2E7A9EE2512857751772F99867D3F9B226DF8F54FCF9B7E9A069ADC64C203A0916CC08848BB04DD05D17F35B0F2A8B63308B6125C3776F015F3A5945FA5835BB01397287BE38F0C307F0466D48FEFA6D328048B7BBAC926C4A47247EE4890137F7D5F97C7B741E8A6EB580B12D13D657280716A135CBEAF6E665AFC5D8D8A850E5462FBB5F569FF37AAD2AD2FA5D32021C17B3206AE26D6BAC5B5C7663346EF55B77519EEC6AAAB7CA210AB967F479903B0AF242800BA9FEFA7D19BD3BCA6BD1F5043F900D4E7CC81CF25B155F845797C01C06521FC05406606CC83FA56937057F9C814657E82222937FFB2CD1E31336AC155D2027AE34AC9ED9580B423ACB36261B0EB8B6A86BA33F6CDA3FF8B7D050E56915F919686640D2605ED38EC9997DC57D0C893A4CDB2DB65E1966DCB049E375E70286B79FA684C445DEA4908A33E23F8BA8ECACDB3BE602E9F3914552A5A908268EA4F\n", "20091203004333 2 6 100 8191 2 DA65275DC4360E7028DEBF433DE3871F40C09D06C1BCEFB64A84F5615ECD9D7C214A9E6CC81E69AC0883013C51665333176FB3E3CDFAD5BC4D24F4FC3E6B06DD312A211B6083FA5BDD0C8D5D1CBC1A1C0CA4DA46B08180E146CD61429E2FDC180D70A325897F534AB6C68DE47306FA79DDA8D963C70F98F2EA50504E834D64510D489E337C8FB75607FE2BFB0573D0FAA1C5A8B050B17B5FB82743E536D41208C35E246AB9D1A37C1E432840ACF2B337E73AA14BF799C078C8398929BE5228777567953B1576518357B008CF6A8379D267664BCAAFAF43D4D655D1C26F5BADCD1ADB5C658247339038C62D96B337A83A7E58575E9BCD12097FC43118731EAA48A573721CCBEBD1E70DF35AFD9BD518A8C8E4EB449D13B0F6B74DDED517FD4D9DD39213713004DAC5D1AC39CAF479F265FDEF080252C18962280C2DD979A338D8D5FB09A821765550ADE72A0B120AF62984AF3CFA89E8D9851EBF9C857903999F72951920D7194A03647F231CBE4D8F933474E4186379BB69776AD5075100E948A5F44C2CFC2E95E43ADC12B1221A53F53CFB562259B25B3784F35753EE28E2A07586C9771BC2FD9C9A6B6C29564EED33F822176274A0F0862EFB463BE24127874D198827A1F567359DEFD1E4EEE35BC59744DD5D59E0902F365AF0D53E25F3065A1848ECAF7A7D2EEEBF4BC6D32AC02752DAE3CE153A0C38581D3A490B89842B3D57B1FD0803E48938C41F5B6490949BC38825102D2F38E22C7FCFABBAACA8E06A8308A32C309F49D0C155070B8EC58310668068BD47AB8329084EF762F145E308526BFD18BBF0A6E668F7B1C500D7849766647ABA60A7C1ECB35A29DA258CF8C2B39C30C0CDAA0F4EF2A0EEC1FEDFD41D1A2BD0A7B08AA109277C349386E4FA8D9083179244E00946BE7105A8CA161A06A9431DC05BD8087ECD72973BACE9CB97E79BC208F5D4AB2D21C4253E1B360D63CF439E06DA9A09FC2AED01C6973D5E0B1DC57B5A288F2F8FA342F58996C04986A8E4B9D67DB4DBFFAD45478FC7491BAAC42D106B28EC8F8759BA71936FC5980EBC5E18F1FD33C700E402827ACF8CC22BFF0841E4C21340765DDAAAD714C157CF067D17F2B13976D7753822FA2E864E1E7797B1B99EDC0950C497B568F6CCDF4CE368B6E03D1734AD9B977D4AFE99EB3650E9B43E6C1567C59A10743E19F3BD045B01825CA2B8086A0C856B17D0C93D8FBFFEB752E95C355817BC842224181BF2EE5A773402573F2E1E9EC819D354FC6FE1CCC287D259E4AC92F20E8060D182C5DC6927A4BA3E55C9D1DD52FE7E732DAF6CA3A1B367172C5071864B32BA323D8BE5FE0D1EA726C8D50266C814843B3F2E46F60611BD0FE166DFD319CE830BEB1C434BB4303A8AF271E474B561958E06946E132482DBAF17D36E6742BE84629F9AF50C8F911F2AEA3AD45362178F6C2B\n" }; /* **************************************************************************** * 8 STATIC FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipssh_authfile_path *=========================================================================== * Description: Forming the full pathname for a key or configuration file. * Should be freed by the caller after using. * Parameters:subdir - The sub folder name in IPCOM_FILE_ROOT * name - The file name * format - The suffix for this file * Returns: IP_NULL - fail to get the full name for this file. * or The full pathname pointer for a file. */ IP_STATIC char * ipssh_authfile_path(const char* subdir, const char* name, const char* format) { char *path = IP_NULL; Ip_size_t path_len = 0; ip_assert(name != IP_NULL); ip_assert(format != IP_NULL); path_len = ipcom_strlen(IPCOM_FILE_ROOT) + ipcom_strlen(name) + ipcom_strlen(format) + 16; if (subdir != IP_NULL) { path_len += ipcom_strlen(subdir); } path = ipcom_malloc(path_len); if (!path) return IP_NULL; /* If there is a subdir configured */ if (subdir != IP_NULL) { ipcom_sprintf(path, "%s%s%s.%s", IPCOM_FILE_ROOT, subdir, name, format); } else { ipcom_sprintf(path, "%s%s.%s", IPCOM_FILE_ROOT, name, format); } return path; } /* *=========================================================================== * ipssh_allow_host_login *=========================================================================== * Description: Verify if this host is allowed to login. * Parameters: user - login user name * host - login host name * Returns: IPCOM_SUCCESS - This user/host is allowed to login. * IPCOM_ERR_FAILED - This user/host is not allowed to login. */ IP_STATIC Ip_err ipssh_allow_host_login(const char* user, const char* host) { char *path = IP_NULL; char *hostname = IP_NULL; char *username = IP_NULL; char line[IPSSH_FILE_LINE_MAX]; IP_FILE *config_file = IP_NULL; Ip_bool hostfind = IP_FALSE; Ip_bool userfind = IP_FALSE; path = ipssh_authfile_path(IPSSH_HOSTBASED_SUBDIR, IPSSH_HOSTBASED_HOSTS, "conf"); if (!path) { IPCOM_LOG0(ERR,"ipssh_allow_host_login path incorrect"); return IPCOM_ERR_NO_MEMORY; } config_file = ipcom_fopen(path, "r"); if (!config_file) { IPCOM_LOG0(ERR,"ipssh_allow_host_login file can not open"); ipcom_free(path); return IPCOM_ERR_FAILED; } /* Read one line of the configuration file */ while (ipcom_fgets(line, IPSSH_FILE_LINE_MAX, (void*)config_file)) { char *last; char *ptr; hostname = IP_NULL; username = IP_NULL; hostfind = IP_FALSE; userfind = IP_FALSE; last = IP_NULL; /* Remove CRNL characters */ ptr = ipcom_strrchr(line, '\n'); if (ptr) *ptr = 0; ptr = ipcom_strrchr(line, '\r'); if (ptr) *ptr = 0; /* Search for the non space charactor */ hostname = ipcom_strtok_r(line," ",&last); if (!hostname) { continue; } /* Find the all match charactor '+' or find the hostname */ if (ipcom_strcmp(hostname, "+") == 0) { hostfind = IP_TRUE; } else if (ipcom_strcmp(hostname, host) == 0) { hostfind = IP_TRUE; } if (!hostfind) { continue; } /* Skip the spaces */ while(*last == ' ') { last++; } while ((username = ipcom_strtok_r(IP_NULL,",",&last)) != IP_NULL) { if (ipcom_strcmp(username, "+") == 0) { userfind = IP_TRUE; break; } if (ipcom_strcmp(username, user) == 0) { userfind = IP_TRUE; break; } } if (userfind) { break; } } if (config_file) ipcom_fclose(config_file); if (path) ipcom_free(path); if ( hostfind == IP_TRUE && userfind == IP_TRUE) { IPCOM_LOG2(DEBUG,"host(%s)/user(%s) is allowed to login",host,user); return IPCOM_SUCCESS; } IPCOM_LOG2(ERR,"ipssh_allow_host_login can not find this user(%s)/host(%s)",host,user); return IPCOM_ERR_FAILED; } #define IPSSH_BEGIN_SSH2_PK "---- BEGIN SSH2 PUBLIC KEY ----" #define IPSSH_END_SSH2_PK "---- END SSH2 PUBLIC KEY ----" /* *=========================================================================== * ipssh_validate_pubkey_ssh2 *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC Ip_err ipssh_validate_pubkey_ssh2(const char* path, EVP_PKEY* pub_key, Ipcom_shell_ctx* sh_ctx) { IP_FILE* fp = IP_NULL; char buf[128]; BIO* mem_bio = IP_NULL; BIO* b64_bio = IP_NULL; Ip_err rc = IPCOM_ERR_FAILED; int bytes_read = 0; Ipcom_buffer* buffer = IP_NULL; EVP_PKEY* local_key = IP_NULL; (void) sh_ctx; fp = ipcom_fopen(path, "r"); if (!fp) goto cleanup; mem_bio = BIO_new(BIO_s_mem()); b64_bio = BIO_new(BIO_f_base64()); if (!mem_bio || ! b64_bio) goto cleanup; BIO_set_flags(b64_bio, BIO_FLAGS_BASE64_NO_NL); BIO_push(b64_bio, mem_bio); while(1) { char* ptr; if (!ipcom_fgets(buf, (int)sizeof(buf), (void*)fp)) goto cleanup; /* Unexpected end of file */ /* Remove CRNL characters */ ptr = ipcom_strrchr(buf, '\n'); if (ptr) *ptr = 0; ptr = ipcom_strrchr(buf, '\r'); if (ptr) *ptr = 0; if (ipcom_strcmp(buf, IPSSH_BEGIN_SSH2_PK) == 0) continue; if (ipcom_strcmp(buf, IPSSH_END_SSH2_PK) == 0) break; if (ipcom_strchr(buf, ':')) continue; /* Header line, skip */ if (BIO_write(mem_bio, buf, (int)ipcom_strlen(buf)) <= 0) goto cleanup; bytes_read += (int)ipcom_strlen(buf); } buffer = ipcom_buffer_new((Ip_size_t)(bytes_read + 16)); if (!buffer) goto cleanup; (void)ipcom_buffer_decr_cap(buffer, 4); /* Save space for blob length, needed by ipssh_buffer_get_put_key */ bytes_read = BIO_read(b64_bio, ipcom_buffer_end_ptr(buffer), (int)ipcom_buffer_capacity(buffer)); if (bytes_read <= 0) goto cleanup; (void)ipcom_buffer_decr_cap(buffer, (Ip_size_t)bytes_read); IP_SET_32ON8(buffer->buf, ip_htonl(bytes_read)); /* Add blob length */ local_key = ipssh_buffer_get_pub_key(buffer); if (!local_key) goto cleanup; if (ipssh_evp_pkey_cmp(local_key, pub_key) == 1) rc = IPCOM_SUCCESS; cleanup: if (fp) ipcom_fclose(fp); if (mem_bio) BIO_free(mem_bio); if (b64_bio) BIO_free(b64_bio); if (local_key) EVP_PKEY_free(local_key); if (buffer) ipcom_buffer_free(buffer); return rc; } /* *=========================================================================== * ipssh_validate_pubkey_by_keyfile *=========================================================================== * Description: Implements a simple public key verifier, called during SSH v2 * authentication handshakes. ipssh_validate_public_key() checks * if the key sent by the client is the same as the key stored in the * local file system. A simple naming convention is used in order to find * the correct file. The path the key file is: * IPCOM_FILE_ROOT/.pk2 * e.g "/ram/roger.pk2". * Files with file extension pk2 is assumed to hold public keys in SSH2 * as specified by the IETF draft. * Alternatively, public keys can be stored in PEM format. The file * format is then: * IPCOM_FILE_ROOT/.pem * e.g. "/ram/roger.pem" * Parameters: * Returns: IPCOM_SUCCESS - The public key is authorized * IPCOM_ERR_FAILED - The public key is rejected or no key file found */ IP_STATIC Ip_err ipssh_validate_pubkey_by_keyfile(const char* subdir, const char* name, EVP_PKEY* pub_key, Ipcom_shell_ctx* sh_ctx) { BIO* bio = IP_NULL; char* path_pem = IP_NULL; char* path_pk = IP_NULL; Ip_err rc = IPCOM_ERR_FAILED; EVP_PKEY* local_key = IP_NULL; path_pk = ipssh_authfile_path(subdir, name, "pk2"); if (!path_pk) { rc = IPCOM_ERR_NO_MEMORY; goto cleanup; } /* Check if we have a .pk2 file with the user's key */ if (ipssh_validate_pubkey_ssh2(path_pk, pub_key, sh_ctx) == IPCOM_SUCCESS) { ipcom_free(path_pk); return IPCOM_SUCCESS; } path_pem = ipssh_authfile_path(subdir, name, "pem"); if (!path_pem) { rc = IPCOM_ERR_NO_MEMORY; goto cleanup; } bio = BIO_new(BIO_s_file()); if (!bio) goto cleanup; if (BIO_read_filename(bio, path_pem) <= 0) { /* No public key file */ goto cleanup; } local_key = PEM_read_bio_PUBKEY(bio, IP_NULL, IP_NULL, IP_NULL); if (!local_key) { goto cleanup; } if (ipssh_evp_pkey_cmp(local_key, pub_key) == 1) rc = IPCOM_SUCCESS; cleanup: if (path_pk) ipcom_free(path_pk); if (path_pem) ipcom_free(path_pem); if (bio) BIO_free(bio); if (local_key) EVP_PKEY_free(local_key); ERR_clear_error(); return rc; } /* **************************************************************************** * 9 GLOBAL FUNCTIONS **************************************************************************** */ IP_GLOBAL void ipssh_create_dh_gex_moduli_example_file(void) { IP_FILE* fp; char* file_path; unsigned int i; file_path = ipcom_sysvar_get("ipssh.kex.dh_gex.moduli_file", IP_NULL, IP_NULL); if (!file_path) { file_path = ipcom_strdup(IPCOM_FILE_ROOT"moduli"); if (!file_path) return; } fp = ipcom_fopen(file_path, "w"); if (!fp) { IPCOM_LOG1(ERR, "ipssh_create_dh_gex_moduli_file :: failed to open file %s", file_path); goto cleanup; } for (i=0; itype != EVP_PKEY_RSA) { IPCOM_LOG1(ERR, "ipssh_load_rsa_key :: key_id %s is not an RSA key", key_id); goto cleanup; } ret = pkey->pkey.rsa; ret->references++; cleanup: if (pkey) EVP_PKEY_free(pkey); return ret; } /* *=========================================================================== * ipssh_load_rsa_key_example_cb *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC RSA* ipssh_load_rsa_key_example_cb(void) { char* key_id; RSA* rsa; key_id = ipcom_sysvar_get("ipssh.key_id.rsa", IP_NULL, 0); if (!key_id) { key_id = ipcom_malloc(ipcom_strlen("default_rsa")+1); if (!key_id) return IP_NULL; ipcom_strcpy(key_id, "default_rsa"); } rsa = ipssh_load_rsa_key_from_key_db(key_id); ipcom_free(key_id); return rsa; } /* *=========================================================================== * ipssh_load_rsa_keyex_key_example_cb *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC RSA* ipssh_load_rsa_keyex_key_example_cb(void) { char* key_id; RSA* rsa; key_id = ipcom_sysvar_get("ipssh.key_id.rsa_keyex", IP_NULL, 0); if (!key_id) { key_id = ipcom_malloc(ipcom_strlen("default_rsa")+1); if (!key_id) return IP_NULL; ipcom_strcpy(key_id, "default_rsa"); } rsa = ipssh_load_rsa_key_from_key_db(key_id); ipcom_free(key_id); return rsa; } #endif /* IPSSH_USE_RSA */ /* *=========================================================================== * ipssh_load_dsa_key_example_cb *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC DSA* ipssh_load_dsa_key_example_cb(void) { DSA *ret = IP_NULL; EVP_PKEY* pkey; char* key_id; key_id = ipcom_sysvar_get("ipssh.key_id.dsa", IP_NULL, 0); if (!key_id) { key_id = ipcom_malloc(ipcom_strlen("default_dsa")+1); if (!key_id) return IP_NULL; ipcom_strcpy(key_id, "default_dsa"); } pkey = ipcom_key_db_pkey_get(key_id); if (!pkey) { IPCOM_LOG1(ERR, "ipssh_load_dsa_key :: failed to get key_id %s", key_id); ret = IP_NULL; goto cleanup; } if (pkey->type != EVP_PKEY_DSA) { IPCOM_LOG1(ERR, "ipssh_load_dsa_key :: key_id %s is not a DSA key", key_id); ret = IP_NULL; goto cleanup; } ret = pkey->pkey.dsa; ret->references++; cleanup: ipcom_free(key_id); if (pkey) EVP_PKEY_free(pkey); return ret; } /* **************************************************************************** * 11 SHELL MANAGEMENT FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipssh_set_win_size *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipssh_set_win_size(Ip_fd shell_fd, Ip_u32 cols, Ip_u32 rows) { IPCOM_LOG2(DEBUG2, "ipssh_set_win_size :: cols=%d, rows=%d", cols, rows); (void) shell_fd; (void) cols; (void) rows; return IPCOM_SUCCESS; } /* **************************************************************************** * 12 AUTHENTICATION FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipssh_validate_userid_pw_example_cb *=========================================================================== * Description: This function is called to validate the userid and password * provided by a client during login. * Parameters: user - the userid provided by the client * pw - the password provided by the client * cookie - this function can return a pointer to cookie * that will be conveyed to the shell start function. * Returns: */ IP_PUBLIC Ip_err ipssh_validate_userid_pw_example_cb(const char *user, const char *pw, Ipcom_shell_ctx* sh_ctx) { (void) sh_ctx; #ifdef IPCOM_USE_AUTH return ipcom_auth_login(user, pw, IP_NULL, IP_NULL, IP_NULL); #else #error YOU_MUST_ADD_AN_AUTHENTICATION_FUNCTION_HERE #endif } /* *=========================================================================== * ipssh_validate_pubkey_example_cb *=========================================================================== * Description: Implements a simple public key verifier, called during SSH v2 * authentication handshakes. ipssh_validate_public_key() checks * if the key sent by the client is the same as the key stored in the * local file system. A simple naming convention is used in order to find * the correct file. The path the key file is: * IPCOM_FILE_ROOT/.pk2 * e.g "/ram/roger.pk2". * Files with file extension pk2 is assumed to hold public keys in SSH2 * as specified by the IETF draft. * Alternatively, public keys can be stored in PEM format. The file * format is then: * IPCOM_FILE_ROOT/.pem * e.g. "/ram/roger.pem" * Parameters: * Returns: IPCOM_SUCCESS - The public key is authorized * IPCOM_ERR_FAILED - The public key is rejected or no key file found */ IP_PUBLIC Ip_err ipssh_validate_pubkey_example_cb(const char* user, EVP_PKEY* pub_key, Ipcom_shell_ctx* sh_ctx) { return ipssh_validate_pubkey_by_keyfile(IP_NULL, user, pub_key, sh_ctx); } /* *=========================================================================== * ipssh_validate_hostbased_example_cb *=========================================================================== * Description: Implements a default simple hostbased authentication verifier, * called during SSH v2 authentication handshakes. * ipssh_validate_hostbased_example_cb() checks * if the key sent by the client is the same as the key stored in the * local file system. A simple naming convention is used in order to find * the correct file. The path the key file is: * IPCOM_FILE_ROOT/host_based/.pk2 * e.g "/ram/host_based/host.corp.ad.wrs.com.pk2". * Files with file extension pk2 is assumed to hold public keys in SSH2 * as specified by the IETF draft. * Alternatively, public keys can be stored in PEM format. The file * format is then: * IPCOM_FILE_ROOT/host_based/host.corp.ad.wrs.com.pem * e.g. "/ram/host_based/host.corp.ad.wrs.com.pem" * Parameters: user - The ssh client user name * host - The ssh client host name * pub_key - The client host key get from msg * sh_ctx - Shell context * Returns: IPCOM_SUCCESS - The public key is authorized * IPCOM_ERR_FAILED - The public key is rejected or no key file found */ IP_PUBLIC Ip_err ipssh_validate_hostbased_example_cb(const char* user, char* host, EVP_PKEY *pub_key, Ipcom_shell_ctx* sh_ctx) { Ip_err rc = IPCOM_ERR_FAILED; int len = 0; #ifdef IPSSH_HOSTBASED_AUTH_DNS_CHECK union Ip_sockaddr_union* claddr = IP_NULL; char *addr_str = IP_NULL; struct Ip_sockaddr *sa; struct Ip_hostent *clhost = IP_NULL; int family = IP_AF_UNSPEC; #endif /* Some processing when the hostname is ended with 'dot'*/ len = ipcom_strlen(host); if (len <= 1) { IPCOM_LOG0(ERR, "ipssh_validate_hostbased_example_cb: hostname is too short\n"); return rc; } if (host[len - 1] == '.') { IPCOM_LOG1(DEBUG, "ipssh_validate_hostbased_example_cb: stripping trailing dot from chost %s", host); host[len - 1] = '\0'; } /* * First check if the 'host + user' is allowed to login, * we checked the 'user name' and don't care of the 'user name on the client host' * as mentioned in rfc that it may be ignored */ rc = ipssh_allow_host_login(user, host); if (rc != IPCOM_SUCCESS) { IPCOM_LOG2(ERR, "ipssh_validate_hostbased_example_cb: user %s host %s is not allowed\n", user, host); return rc; } #ifdef IPSSH_HOSTBASED_AUTH_DNS_CHECK /* * RFC4252 Chapter 9 * it is RECOMMENDED that the server perform * additional checks to verify that the network address obtained from * the (untrusted) network matches the given client host name */ claddr = ipcom_shell_ctx_get_peer_addr(sh_ctx); if (IP_NULL == claddr) { IPCOM_LOG0(ERR, "ipssh_validate_hostbased_example_cb: get peer address failed\n"); return IPCOM_ERR_FAILED; } sa = (struct Ip_sockaddr *)claddr; #ifdef IPCOM_USE_INET6 if (sa->sa_family == IP_AF_INET6) { struct Ip_sockaddr_in6 *sin6; sin6 = (struct Ip_sockaddr_in6 *)claddr; #ifdef IPSSH_V6_MAPPED_V4_ADDR_NOT_SUPPORTED addr_str = (char *)(sin6->sin6_addr.in6.addr32); family = IP_AF_INET6; #else if (IP_IN6_IS_ADDR_V4MAPPED(&(sin6->sin6_addr))) { addr_str = (char *)(&sin6->sin6_addr.in6.addr32[3]); family = IP_AF_INET; } else { addr_str = (char *)(sin6->sin6_addr.in6.addr32); family = IP_AF_INET6; } } #endif #endif #ifdef IPCOM_USE_INET if (sa->sa_family == IP_AF_INET) { addr_str = (char *)(&claddr->sin.sin_addr); family = IP_AF_INET; } #endif /* To get the host information by ip address of this IPSSH connection */ clhost = ipcom_gethostbyaddr(addr_str, family == IP_AF_INET ? 4 : 16, family); if (IP_NULL == clhost) { IPCOM_LOG0(ERR, "ipssh_validate_hostbased_example_cb: get host by address failed\n"); return IPCOM_ERR_FAILED; } /* Check if hostname in SSH_MSG_USERAUTH_REQUEST is the same with the one * we find by ipcom_gethostbyaddr. * It not match, there is possibility that the hostname in msg is forged. */ if (ipcom_strcmp(host,clhost->h_name) != 0) { IPCOM_LOG0(ERR, "ipssh_validate_hostbased_example_cb: host name check failed\n"); return IPCOM_ERR_FAILED; } #endif /* * Validate that the public key in SSH_MSG_USERAUTH_REQUEST * msg is the same with the one in server's local key file. * */ rc = ipssh_validate_pubkey_by_keyfile(IPSSH_HOSTBASED_SUBDIR, host, pub_key, sh_ctx); if (rc != IPCOM_SUCCESS) { IPCOM_LOG1(ERR, "ipssh_validate_hostbased_example_cb: host(%s) key validation failed.",host); return rc; } IPCOM_LOG1(DEBUG, "ipssh_validate_hostbased_example_cb: host(%s) key validation suceed.",host); return IPCOM_SUCCESS; } /* *=========================================================================== * ipssh_validate_rsa_pubkey_v1_example_cb *=========================================================================== * Description: This is an example key validation function. It is called during * a SSH v1 RSA authentication handshake. The client sends its * public key modulus which is provided as argument to this function. * The function checks whether the user has an authorized public * key with the provided modulus. * * The path the key file is: * IPCOM_FILE_ROOT/_.pub * e.g. "/ram/keys/roger.pub" * The key is assumed to be stored in SSH format, i.e. each line has the * following format: * * * Parameters: user - name of client performing RSA authentication * modulus - the modulus (n) of the public key the client wants to use for authentication. * Returns: If the user has an authorized key with the provided modulus, * the complete public key, i.e. both modulus (n) and public exponent * (e), is returned. If not, NULL is returned which will lead to this * authentication request being rejected. */ #ifdef IPSSH_USE_V1 IP_PUBLIC RSA* ipssh_validate_rsa_pubkey_v1_example_cb(const char *user, BIGNUM *modulus, Ipcom_shell_ctx* sh_ctx) { char *line = IP_NULL; char *key_str; char *filename; RSA *rsa = IP_NULL; IP_FILE *key_file; int success = 0; (void)sh_ctx; filename = ipcom_malloc(ipcom_strlen(IPCOM_FILE_ROOT)+ipcom_strlen(user)+16); if (!filename) return IP_NULL; ipcom_sprintf(filename, "%s/%s.pub", IPCOM_FILE_ROOT, user); key_file = ipcom_fopen(filename, "r"); if (!key_file) goto cleanup; line = ipcom_malloc(1024); if (!line) goto cleanup; rsa = RSA_new(); if (!rsa) goto cleanup; while (ipcom_fgets(line, 1024, (void*)key_file)) { int i; char *last; /* Skip first entry (no of bits)*/ for (key_str = ipcom_strtok_r(line, " ", &last), i=0; key_str != IP_NULL && i<1; key_str = ipcom_strtok_r(IP_NULL, " ", &last), i++); if (!key_str) continue; /* Obviously no key on this line */ if (!BN_dec2bn(&rsa->e, key_str)) continue; key_str = ipcom_strtok_r(IP_NULL, " ", &last); if (!key_str) continue; if (!BN_dec2bn(&rsa->n, key_str)) continue; if (BN_cmp(rsa->n, modulus) == 0) { success = 1; break; } } cleanup: if (filename) ipcom_free(filename); if (key_file) ipcom_fclose(key_file); if (line) ipcom_free(line); if (success) return rsa; else { if (rsa) RSA_free(rsa); return IP_NULL; } } #endif /* IPSSH_USE_V1 */ IP_PUBLIC Ip_err ipssh_auth_complete_example_cb(const char* user, Ipcom_shell_ctx* sh_ctx) { #ifdef IPTESTENGINE char* root_dir; /* Check if root dir is already set */ if (ipcom_shell_ctx_get(sh_ctx, IPSSH_SFTP_ROOT_DIR, IP_NULL, IP_NULL) == IPCOM_SUCCESS) return IPCOM_SUCCESS; root_dir = ipcom_sysvar_get("ipssh.sftp.session_root_dir", IP_NULL, IP_NULL); if (!root_dir) return IPCOM_SUCCESS; IPCOM_LOG1(DEBUG, "ipssh_auth_complete_cb :: session root dir: %s", root_dir); if (ipcom_shell_ctx_add(sh_ctx, IPSSH_SFTP_ROOT_DIR, (Ip_u8*)root_dir, ipcom_strlen(root_dir)+1) != IPCOM_SUCCESS) { IPCOM_LOG0(ERR, "ipssh_auth_complete_cb :: failed to store sftp root dir in shell ctx"); ipcom_free(root_dir); return IPCOM_ERR_FAILED; } ipcom_free(root_dir); #endif (void)user; (void)sh_ctx; return IPCOM_SUCCESS; } /* *=========================================================================== * ipssh_validate_srv_public_key_example_cb *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipssh_validate_srv_public_key_example_cb(EVP_PKEY *srv_key, const union Ip_sockaddr_union *srv_addr) { (void) srv_key; (void) srv_addr; return IPCOM_SUCCESS; } /* **************************************************************************** * 13 C API FUNCTIONS **************************************************************************** * The following functions are part of the C API to integrate a shell with * SSH. * - ipssh_shell_stdin_cb * - ipssh_shell_stop_cb * - ipssh_shell_start_cb * - ipssh_get_clt_fd * - ipssh_shell_welcome_msg_cb * The functions are deprecated and will be removed in the next major * VxWorks release. Please migrate to the socket model for integrating * a shell. */ /* *=========================================================================== * ipssh_shell_stdin_cb *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipssh_shell_stdin_cb(void *ssh_ctx, void *shell_ctx, const char *data, int len) { return IPCOM_SUCCESS; } /* *=========================================================================== * ipssh_shell_stop_cb *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipssh_shell_stop_cb(void *ssh_ctx, void *shell_ctx) { return IPCOM_SUCCESS; } /* *=========================================================================== * ipssh_shell_start_cb *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC void* ipssh_shell_start_cb(void* ssh_ctx, const char* user, Ipcom_shell_ctx* sh_ctx) { return IP_NULL; } /* *=========================================================================== * ipssh_shell_welcome_msg_output *=========================================================================== * Description: This function is called when a shell has been created and all * IPSSH internal setup has been done. The main purpose of this * callback is to enable the output of a welcome message or banner. * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipssh_shell_welcome_msg_cb(void *ssh_ctx, void *shell_ctx) { return IPCOM_SUCCESS; } /* **************************************************************************** * END OF FILE **************************************************************************** */