int Condor_Auth_Passwd::authenticate(const char * /* remoteHost */, CondorError* /* errstack */ ) { int client_status = AUTH_PW_A_OK; int server_status = AUTH_PW_A_OK; int ret_value = -1; struct msg_t_buf t_client; struct msg_t_buf t_server; // In order to create the shared keys used by the client and // the server in this protocol, we take a single shared secret // and hmac it twice with two different keys. The original // password buffer and the two generated keys are stored in // the sk_buf structure. struct sk_buf sk; int tmp_rv; // Initialize these structures (with NULLs) init_t_buf(&t_client); init_t_buf(&t_server); init_sk(&sk); dprintf(D_SECURITY, "PW.\n"); if ( mySock_->isClient() ) { // ** client side authentication ** // Get my name, password and setup the shared keys based // on this data. The server will do the same when it // learns my name. dprintf(D_SECURITY, "PW: getting name.\n"); t_client.a = fetchLogin(); // We complete the entire protocol even if there's an // error, but there's no point trying to actually do any // work. This is protocol step (a). dprintf(D_SECURITY, "PW: Generating ra.\n"); if(client_status == AUTH_PW_A_OK) { t_client.ra = Condor_Crypt_Base::randomKey(AUTH_PW_KEY_LEN); if(!t_client.ra) { dprintf(D_SECURITY, "Malloc error in random key?\n"); client_status = AUTH_PW_ERROR; } } // This differs from the protocol description in the book // only that the client also sends its name "A". The // protocol doesn't mention how the peers know who they're // talking to. This is also protocol step (a). dprintf(D_SECURITY, "PW: Client sending.\n"); client_status = client_send_one(client_status, &t_client); if(client_status == AUTH_PW_ABORT) { goto client_abort; } // This is protocol step (b). dprintf(D_SECURITY, "PW: Client receiving.\n"); server_status = client_receive(&client_status, &t_server); if(client_status == AUTH_PW_ABORT) { goto client_abort; } // Now that we've received the server's name, we can go // ahead and setup the keys. if(client_status == AUTH_PW_A_OK && server_status == AUTH_PW_A_OK) { sk.shared_key = fetchPassword(t_client.a, t_server.b); dprintf(D_SECURITY, "PW: Client setting keys.\n"); if(!setup_shared_keys(&sk)) { client_status = AUTH_PW_ERROR; } } // This is protocol step (c). if(client_status == AUTH_PW_A_OK && server_status == AUTH_PW_A_OK) { dprintf(D_SECURITY, "PW: Client checking T.\n"); client_status = client_check_t_validity(&t_client, &t_server, &sk); } // Are we copying the data into the t_client struct? // This is protocol step (d). Server does (e). dprintf(D_SECURITY, "PW: CLient sending two.\n"); client_status = client_send_two(client_status, &t_client, &sk); if(client_status == AUTH_PW_ABORT) { goto client_abort; } client_abort: // This is protocol step (f). if(client_status == AUTH_PW_A_OK && server_status == AUTH_PW_A_OK && set_session_key(&t_client, &sk)) { dprintf(D_SECURITY, "PW: CLient set session key.\n"); ret_value = 1; } else { ret_value = 0; } } else { // ** server side authentication ** // First we get the client's name and ra, protocol step // (a). dprintf(D_SECURITY, "PW: Server receiving 1.\n"); client_status = server_receive_one(&server_status, &t_client); if(client_status == AUTH_PW_ABORT || server_status == AUTH_PW_ABORT) { goto server_abort; } // Then we do the key setup, and generate the random string. if(client_status == AUTH_PW_A_OK && server_status == AUTH_PW_A_OK) { t_server.b = fetchLogin(); dprintf(D_SECURITY, "PW: Server fetching password.\n"); sk.shared_key = fetchPassword(t_client.a, t_server.b); if(!setup_shared_keys(&sk)) { server_status = AUTH_PW_ERROR; } else { dprintf(D_SECURITY, "PW: Server generating rb.\n"); //server_status = server_gen_rand_rb(&t_server); t_server.rb = Condor_Crypt_Base::randomKey(AUTH_PW_KEY_LEN); if(t_client.a) { t_server.a = strdup(t_client.a); } else { t_server.a = NULL; } t_server.ra = (unsigned char *)malloc(AUTH_PW_KEY_LEN); if(!t_server.ra || !t_server.rb) { dprintf(D_SECURITY, "Malloc error 1.\n"); server_status = AUTH_PW_ERROR; } else { memcpy(t_server.ra, t_client.ra, AUTH_PW_KEY_LEN); } } } // Protocol message (2), step (b). dprintf(D_SECURITY, "PW: Server sending.\n"); tmp_rv = server_send(server_status, &t_server, &sk); if(server_status == AUTH_PW_A_OK) { server_status = tmp_rv; } if(server_status == AUTH_PW_ABORT) { goto server_abort; } // Protocol step (d) dprintf(D_SECURITY, "PW: Server receiving 2.\n"); if(t_server.a) { t_client.a = strdup(t_server.a); } else { t_client.a = NULL; } if(server_status == AUTH_PW_A_OK) { t_client.rb = (unsigned char *)malloc(AUTH_PW_KEY_LEN); if(!t_client.rb) { dprintf(D_SECURITY, "Malloc_error.\n"); server_status = AUTH_PW_ERROR; } else { memcpy(t_client.rb, t_server.rb, AUTH_PW_KEY_LEN); } } else { t_client.rb = NULL; } client_status = server_receive_two(&server_status, &t_client); if(server_status == AUTH_PW_A_OK && client_status == AUTH_PW_A_OK) { // Protocol step (e) dprintf(D_SECURITY, "PW: Server checking hk.\n"); server_status = server_check_hk_validity(&t_client, &t_server, &sk); } server_abort: // protocol step (f) if(client_status == AUTH_PW_A_OK && server_status == AUTH_PW_A_OK && set_session_key(&t_server, &sk)) { dprintf(D_SECURITY, "PW: Server set session key.\n"); ret_value = 1; } else { ret_value = 0; } } //ret_value is 1 for success, 0 for failure. if ( ret_value == 1 ) { // if all is good, set the remote user and domain names char *login, *domain; if ( mySock_->isClient() ) { login = t_server.b; // server is remote to client } else { login = t_client.a; // client is remote to server } ASSERT(login); domain = strchr(login,'@'); if (domain) { *domain='\0'; domain++; } setRemoteUser(login); setRemoteDomain(domain); } destroy_t_buf(&t_client); destroy_t_buf(&t_server); destroy_sk(&sk); //return 1 for success, 0 for failure. Server should send //sucess/failure back to client so client can know what to //return. return ret_value; }
int main(int argc, char **argv) { int status; char ip_addr[INET_ADDRSTRLEN]; char *service; int server_sock = -1; int exit_flag = 0; int ftp_sock = 9999; fd_set temp; /*Init. Logger*/ #ifndef MY_PC cse4589_init_log(argv[2]); #endif int sock; if(argc<3) { printf("No args\n"); return 1; } if(!validate_port(argv[2])) return 0; FD_ZERO(&wait_fd); FD_ZERO(&temp); FD_SET(0, &wait_fd); tv.tv_sec = 15; tv.tv_usec = 0; if(!strcmp(argv[1], "s")) { is_server = true; } else if(strcmp(argv[1], "c")) { printf("Usage ./sock [s/c]\n"); return 0; } set_listening_port(argv[2]); server_sock = server_start(argv[2]); if(server_sock <=0)return 0; sock = server_sock; add_fd(sock); int i =2; while(!exit_flag) { temp = wait_fd; int ret = select(active_sockets, &temp, NULL, NULL, NULL); if(ret) { if(FD_ISSET(STDIN, &temp)) { exit_flag = parse_shell(); } else if(FD_ISSET(server_sock, &temp)) { // server socket is active, check for new connections if(is_server) { int new_socket = server_accept(server_sock); add_fd(new_socket); } else { int new_socket = server_accept(server_sock); //add ftp socket add_fd(new_socket); ftp_sock = new_socket; } } else if(FD_ISSET(ftp_sock, &temp)) { client_receive_file(&ftp_sock); } else { for(int fd = 3; fd<=active_sockets; fd++) { if(FD_ISSET(fd, &temp)) { if(is_server) server_receive(fd); else client_receive(fd); } } } //End of else } //end of select handling } //end loop clear_fd(sock); close(sock); #ifndef MY_PC fclose(fopen(LOGFILE, "w")); #endif return 0; }