GME
13
|
00001 00023 #include "../StdAfx.h" 00024 00025 #if(USESVN) 00026 00027 #include "Prompter.h" 00028 #include "Pool.h" 00029 #include "svn_client.h" 00030 #include "conio.h" 00031 #include "Util.h" 00032 #include "..\\CredentialDlg.h" 00033 #include "..\\CertificateDlg.h" 00034 #include <iostream> // remove this later 00035 00036 extern std::string g_userName; 00037 extern std::string g_passWord; 00038 00039 //static 00040 void PromptImpl::scanfBlind( std::string& ret) 00041 { 00042 ASSERT(0); 00043 int k = 0; 00044 ret.clear(); 00045 00046 // blind scanf like: 00047 while( 13 != ( k = getch()) && 10 != k) 00048 { 00049 if( k != 8) 00050 { 00051 std::cout << "*"; 00052 ret += (char) k; 00053 } 00054 else 00055 { 00056 ret = ret.substr( 0, ret.length() - 1); // remove last one 00057 std::cout << "Backspace, please continue typing " << std::endl << std::string( ret.length(), '*'); 00058 } 00059 } 00060 if( k == 13 || k == 10) 00061 std::cout << std::endl; 00062 } 00063 00064 GPromptImpl::GPromptImpl() 00065 : m_pWord( "-") 00066 , m_uName( "-") 00067 , m_credsFilled( false) 00068 { 00069 } 00070 00071 GPromptImpl::~GPromptImpl() 00072 { 00073 } 00074 00075 std::string GPromptImpl::username() 00076 { 00077 // assumes that prompt() was called before, 00078 // and the m_uName field was filled already 00079 if( m_credsFilled && m_uName.size() > 0 && m_uName != "-") // the default value 00080 return m_uName; 00081 00082 ASSERT(0); 00083 CCredentialDlg dlg( true, false, false, m_uName, (const char*) 0); 00084 if( dlg.DoModal() == IDOK) 00085 { 00086 m_uName = dlg.name(); 00087 //m_pWord = dlg.word(); 00088 //m_credsFilled = true; 00089 } 00090 00091 return m_uName; 00092 } 00093 00094 std::string GPromptImpl::password() 00095 { 00096 if( m_credsFilled && m_pWord.size() > 0 && m_pWord != "-")// && m_maySave) // if not the default value ("-") and only if allowed to be saved 00097 return m_pWord; 00098 00099 ASSERT(0); 00100 CCredentialDlg dlg( false, false, false, m_uName, (const char*) 0); 00101 if( dlg.DoModal() == IDOK) 00102 { 00103 m_uName = dlg.name(); 00104 m_pWord = dlg.word(); 00105 m_credsFilled = true; 00106 } 00107 return m_pWord; 00108 } 00109 00110 bool GPromptImpl::askYesNo(const char *realm, const char *question, 00111 bool yesIsDefault) 00112 { 00113 std::string msg = "Realm: " + std::string( realm ? realm:"<norealm>") + "\nQuestion: " + std::string( question ? question :"<noquestion>"); 00114 int res = AfxMessageBox( msg.c_str(), MB_YESNO); 00115 if( IDYES == res) 00116 return true; 00117 else if( IDNO == res) 00118 return false; 00119 else 00120 return yesIsDefault; 00121 } 00122 00123 std::string GPromptImpl::askQuestion(const char *realm, const char *question, 00124 bool showAnswer, bool maySave) 00125 { 00126 std::string msg = "Realm: " + std::string( realm ? realm:"<norealm>") + "\nQuestion: " + std::string( question ? question :"<noquestion>"); 00127 if( IDYES == AfxMessageBox( msg.c_str(), MB_YESNO)) 00128 m_answer = "y"; 00129 else 00130 m_answer = "n"; 00131 00132 m_maySave = false; 00133 msg = "May save the answer?"; 00134 if( IDYES == AfxMessageBox( msg.c_str(), MB_YESNO)) 00135 m_maySave = true; 00136 00137 return m_answer; 00138 } 00139 00140 int GPromptImpl::askTrust(const char *question, bool maySave) 00141 { 00142 std::string q = question; 00143 int offs = 0; // make it Windows multiline: \r\n instead of \n 00144 while( (offs = q.find( '\n', offs + 1)) != -1) 00145 { 00146 q.insert( offs, "\r"); offs += 2; 00147 } 00148 //if(maySave) 00149 //{ 00150 // q += "(R)eject, accept (t)emporarily or accept (p)ermanently?"; 00151 //} 00152 //else 00153 //{ 00154 // q += "(R)eject or accept (t)emporarily?"; 00155 //} 00156 00157 CCertificateDlg dlg( q, maySave, 0); 00158 if( dlg.DoModal() == IDOK) 00159 { 00160 CCertificateDlg::Response rp = dlg.getResp(); 00161 if( rp == CCertificateDlg::PermanentAccept) 00162 return Prompter::AcceptPermanently; 00163 else if( rp == CCertificateDlg::TemoraryAccept) 00164 return Prompter::AcceptTemporary; 00165 else 00166 return Prompter::Reject; 00167 } 00168 return Prompter::Reject; 00169 } 00170 00171 bool GPromptImpl::prompt(const char *p_realm, const char *p_username, bool p_maySave) 00172 { 00173 std::string u_name( p_username?p_username: "<<nousername>>"); 00174 //std::string msg = "Realm: \t'" + std::string( p_realm?p_realm:"<<norealm>>") + "'\nUser: \t'" + u_name + "'\nChange user credentials?"; 00175 //if( IDYES == AfxMessageBox( msg.c_str(), MB_YESNO)) 00176 if( 1) 00177 { 00178 CCredentialDlg dlg( false, true, p_maySave, u_name, p_realm); 00179 if( dlg.DoModal() == IDOK) 00180 { 00181 m_uName = dlg.name(); 00182 m_pWord = dlg.word(); 00183 m_credsFilled = true; 00184 if( p_maySave) 00185 { 00186 m_maySave = dlg.maySave(); 00187 if( m_maySave) 00188 { 00189 g_userName = m_uName; 00190 g_passWord = m_pWord; 00191 // todo: then save it by using the special set_password 00192 // 00193 } 00194 } 00195 else 00196 m_maySave = false; 00197 } 00198 } 00199 else // User selected not to change user credentials 00200 { 00201 m_uName = p_username; 00202 //m_pWord = "-"; 00203 } 00204 00205 return true; 00206 } 00207 00208 00209 //#include "svn_private_config.h" 00210 TextPromptImpl::TextPromptImpl() 00211 : m_pWord( "-") 00212 , m_uName( "-") 00213 { 00214 } 00215 00216 std::string TextPromptImpl::readcnf( const EntryType& p_type) 00217 { 00218 if( p_type == UserName) 00219 { 00220 return "username"; 00221 } 00222 else if( p_type == Password) 00223 { 00224 return m_pWord.size() > 0 ? m_pWord : "<<no pw?>>"; 00225 } 00226 return ""; 00227 } 00228 00229 TextPromptImpl::~TextPromptImpl() 00230 { 00231 } 00232 00233 std::string TextPromptImpl::username() 00234 { 00235 // assumes that prompt() was called before, 00236 // and the m_uName field was filled already 00237 00238 if( m_uName.size() > 0 && m_uName != "-") // the default value 00239 return m_uName; 00240 00241 return readcnf( UserName); 00242 } 00243 00244 std::string TextPromptImpl::password() 00245 { 00246 if( m_pWord.size() > 0 && m_pWord != "-" && m_maySave) // if not the default value ("-") and only if allowed to be saved 00247 return m_pWord; 00248 00249 // require it 00250 std::cout << "Password please : "; 00251 std::string ret; 00252 scanfBlind( ret); 00253 //if( 1 == scanf( "%s", &buff)) // cin eliminates whitespaces 00254 //ret = buff; 00255 //ret = readcnf( EntryType::Password); 00256 00257 if( m_maySave) 00258 { 00259 m_pWord = ret; 00260 } 00261 return ret; 00262 } 00263 00264 bool TextPromptImpl::askYesNo(const char *realm, const char *question, 00265 bool yesIsDefault) 00266 { 00267 std::cout << "\nRealm: " << (realm?realm:"<<norealm>>") << "\nQuestion: " << question; 00268 00269 //int k = getch(); 00270 std::string res; 00271 std::cin >> res; 00272 int k = res.size() > 0 ? res[0]: ' '; 00273 if( (char) k == 'n' || (char) k == 'N') 00274 return false; 00275 else if( (char) k == 'y' || (char) k == 'Y') 00276 return true; 00277 else // if yesIsDefault return true = Yes, if !yesisDefault return false = No 00278 return yesIsDefault; 00279 } 00280 00281 std::string TextPromptImpl::askQuestion(const char *realm, const char *question, 00282 bool showAnswer, bool maySave) 00283 { 00284 std::cout << "\nRealm: " << (realm?realm:"<norealm>") << "\nQuestion: " << (question?question:"<noquestion>"); 00285 std::string ret; 00286 std::cin >> ret; 00287 m_answer = ret; 00288 if(maySave) 00289 m_maySave = askYesNo(realm, "May save the answer ?", true); 00290 else 00291 m_maySave = false; 00292 00293 return m_answer; 00294 } 00295 00296 int TextPromptImpl::askTrust(const char *question, bool maySave) 00297 { 00298 std::string q = question; 00299 if(maySave) 00300 { 00301 q += "(R)eject, accept (t)emporarily or accept (p)ermanently?"; 00302 } 00303 else 00304 { 00305 q += "(R)eject or accept (t)emporarily?"; 00306 } 00307 std::string s_answer = askQuestion( NULL, q.c_str(), true, false); 00308 char answer = (s_answer.size() > 0)? s_answer[0]: ' '; 00309 if( answer == 't' || answer == 'T') 00310 { 00311 return Prompter::AcceptTemporary; 00312 } 00313 else if(maySave && (answer == 'p' || answer == 'P')) 00314 { 00315 return Prompter::AcceptPermanently; 00316 } 00317 else 00318 return Prompter::Reject; 00319 } 00320 00321 bool TextPromptImpl::prompt(const char *p_realm, const char *p_username, bool p_maySave) 00322 { 00323 // aren't we too ambitious here 00324 std::cout << "\nRealm: " << (p_realm?p_realm:"<<norealm>>") << std::endl << "-Username-: '" << (p_username?p_username: "<<zerousernameptr>>") << "'"; 00325 if( askYesNo( p_realm, "Change user name?", false)) 00326 { 00327 std::cout << "Username please : "; 00328 std::cin >> m_uName; // what about storing retv somewhere? 00329 00330 std::cout << "Password for '" << m_uName << "' please : "; 00331 scanfBlind( m_pWord); 00332 00333 if( p_maySave) 00334 { 00335 m_maySave = askYesNo( p_realm, "May save the answer ?", true); 00336 if( m_maySave) 00337 { 00338 g_userName = m_uName; 00339 g_passWord = m_pWord; 00340 // todo: then save it by using the special set_password 00341 // 00342 } 00343 } 00344 else 00345 m_maySave = false; 00346 00347 return true; 00348 } 00349 else 00350 m_uName = p_username; 00351 00352 return true; 00353 } 00354 00355 //************************************** 00356 //************************************* 00357 00358 Prompter::Prompter( PromptImpl* p_prompter) 00359 { 00360 m_impl = p_prompter; 00361 } 00362 00363 Prompter::~Prompter() 00364 { 00365 if( m_impl) 00366 { 00367 delete m_impl; 00368 } 00369 } 00370 00371 Prompter* Prompter::makePrompter( PromptImpl* p_promptImpl) 00372 { 00373 return new Prompter( p_promptImpl); 00374 } 00375 00376 svn_auth_provider_object_t* Prompter::getProviderSimple(apr_pool_t *pool) 00377 { 00378 svn_auth_provider_object_t *provider; 00379 svn_client_get_simple_prompt_provider (&provider, 00380 CallbackHelpers::simple_prompt, /* prompt function */ 00381 m_impl, /* prompt baton */ 00382 2, /* retry limit */ 00383 pool); 00384 00385 return provider; 00386 } 00387 00388 svn_auth_provider_object_t* Prompter::getProviderUsername(apr_pool_t *pool) 00389 { 00390 svn_auth_provider_object_t *provider; 00391 svn_client_get_username_prompt_provider (&provider, 00392 CallbackHelpers::username_prompt, /* prompt function */ 00393 m_impl, /* prompt baton */ 00394 2, /* retry limit */ 00395 pool); 00396 00397 return provider; 00398 } 00399 00400 svn_auth_provider_object_t* Prompter::getProviderServerSSLTrust(apr_pool_t *pool) 00401 { 00402 svn_auth_provider_object_t *provider; 00403 svn_client_get_ssl_server_trust_prompt_provider 00404 (&provider, CallbackHelpers::ssl_server_trust_prompt, m_impl, pool); 00405 00406 return provider; 00407 } 00408 00409 svn_auth_provider_object_t* Prompter::getProviderClientSSL(apr_pool_t *pool) 00410 { 00411 svn_auth_provider_object_t *provider; 00412 svn_client_get_ssl_client_cert_prompt_provider 00413 (&provider, CallbackHelpers::ssl_client_cert_prompt, m_impl, 2, /* retry limit */pool); 00414 00415 return provider; 00416 } 00417 00418 svn_auth_provider_object_t* Prompter::getProviderClientSSLPassword(apr_pool_t *pool) 00419 { 00420 svn_auth_provider_object_t *provider; 00421 svn_client_get_ssl_client_cert_pw_prompt_provider 00422 (&provider, CallbackHelpers::ssl_client_cert_pw_prompt, m_impl, 2 /* retry limit */, 00423 pool); 00424 00425 return provider; 00426 } 00427 00428 // ********************************************************************************************* 00429 // *********************** C A L L B A C K H E L P E R M E T H O D S *********************** 00430 // ********************************************************************************************* 00431 00432 // static, callback 00433 svn_error_t *Prompter::CallbackHelpers::simple_prompt(svn_auth_cred_simple_t **cred_p, 00434 void *baton, 00435 const char *realm, const char *username, 00436 svn_boolean_t may_save, 00437 apr_pool_t *pool) 00438 { 00439 // SVN_AUTH_CRED_SIMPLE [svn.simple] credentials ( svn_auth_cred_simple_t ) comprise of 00440 // const char *username; 00441 // const char *password; 00442 // svn_boolean_t may_save; 00443 // This latter indicates if the credentials may be saved (to disk). 00444 // For example, a GUI prompt implementation with a remember password 00445 // checkbox shall set may_save to TRUE if the checkbox is checked. 00446 00447 PromptImpl *that = (PromptImpl*)baton; 00448 svn_auth_cred_simple_t *ret = (svn_auth_cred_simple_t*)apr_pcalloc(pool, sizeof(*ret)); 00449 00450 // show dlg 00451 if(!that->prompt( realm, username, may_save ? true : false)) 00452 return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog"); 00453 00454 // retrieve uname 00455 std::string user = that->username(); 00456 if(user == "") 00457 return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog"); 00458 00459 // duplicate uname into return variable 00460 ret->username = apr_pstrdup( pool, user.c_str()); 00461 00462 // retrieve passwrd 00463 std::string pass = that->password(); 00464 if(pass == "") 00465 return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog"); 00466 00467 // duplicate password into return variable 00468 ret->password = apr_pstrdup( pool, pass.c_str()); 00469 00470 // retrieve may_save option 00471 ret->may_save = that->m_maySave; 00472 00473 *cred_p = ret; 00474 return SVN_NO_ERROR; 00475 } 00476 00477 // static, callback 00478 svn_error_t* Prompter::CallbackHelpers::username_prompt(svn_auth_cred_username_t **cred_p, 00479 void *baton, 00480 const char *realm, 00481 svn_boolean_t may_save, 00482 apr_pool_t *pool) 00483 { 00484 // SVN_AUTH_CRED_USERNAME [svn.username] credentials ( svn_auth_cred_username_t ) comprise of 00485 // const char *username; 00486 // svn_boolean_t may_save; 00487 // This latter indicates if the credentials may be saved (to disk). 00488 // For example, a GUI prompt implementation with a remember username 00489 // checkbox shall set may_save to TRUE if the checkbox is checked. 00490 00491 PromptImpl *that = (PromptImpl*)baton; 00492 svn_auth_cred_username_t *ret = (svn_auth_cred_username_t*)apr_pcalloc(pool, sizeof(*ret)); 00493 00494 // show question 00495 std::string user = that->askQuestion( realm, "[svn.username] Username: ", true, may_save ? true : false); 00496 if(user == "") 00497 return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog"); 00498 00499 // duplicate uname into return variable 00500 ret->username = apr_pstrdup(pool,user.c_str()); 00501 00502 // retrieve may_save option 00503 ret->may_save = that->m_maySave; 00504 00505 *cred_p = ret; 00506 return SVN_NO_ERROR; 00507 } 00508 00509 // static, callback 00510 svn_error_t* Prompter::CallbackHelpers::ssl_server_trust_prompt( 00511 svn_auth_cred_ssl_server_trust_t **cred_p, 00512 void *baton, 00513 const char *realm, 00514 apr_uint32_t failures, 00515 const svn_auth_ssl_server_cert_info_t *cert_info, 00516 svn_boolean_t may_save, 00517 apr_pool_t *pool) 00518 { 00519 PromptImpl *that = (PromptImpl*)baton; 00520 svn_auth_cred_ssl_server_trust_t *ret = (svn_auth_cred_ssl_server_trust_t*)apr_pcalloc(pool, sizeof(*ret)); 00521 00522 std::string question = "Error validating server certificate for "; 00523 question += realm; 00524 question += ":\n"; 00525 00526 if(failures & SVN_AUTH_SSL_UNKNOWNCA) 00527 { 00528 question += " - Unknown certificate issuer\n"; 00529 question += " Fingerprint: "; 00530 question += cert_info->fingerprint; 00531 question += "\n"; 00532 question += " Distinguished name: "; 00533 question += cert_info->issuer_dname; 00534 question += "\n"; 00535 } 00536 00537 if(failures & SVN_AUTH_SSL_CNMISMATCH) 00538 { 00539 question += " - Hostname mismatch ("; 00540 question += cert_info->hostname; 00541 question += ")\n"; 00542 } 00543 00544 if(failures & SVN_AUTH_SSL_NOTYETVALID) 00545 { 00546 question += " - Certificate is not yet valid\n"; 00547 question += " Valid from "; 00548 question += cert_info->valid_from; 00549 question += "\n"; 00550 } 00551 00552 if(failures & SVN_AUTH_SSL_EXPIRED) 00553 { 00554 question += " - Certificate is expired\n"; 00555 question += " Valid until "; 00556 question += cert_info->valid_until; 00557 question += "\n"; 00558 } 00559 00560 switch( that->askTrust( question.c_str(), may_save ? true : false)) 00561 { 00562 case AcceptTemporary: 00563 *cred_p = ret; 00564 ret->may_save = FALSE; 00565 break; 00566 case AcceptPermanently: 00567 *cred_p = ret; 00568 ret->may_save = TRUE; 00569 ret->accepted_failures = failures; 00570 break; 00571 default: 00572 *cred_p = NULL; 00573 } 00574 return SVN_NO_ERROR; 00575 } 00576 00577 // static, callback 00578 svn_error_t* Prompter::CallbackHelpers::ssl_client_cert_prompt( 00579 svn_auth_cred_ssl_client_cert_t **cred_p, 00580 void *baton, 00581 const char *realm, 00582 svn_boolean_t may_save, 00583 apr_pool_t *pool) 00584 { 00585 PromptImpl *that = (PromptImpl*)baton; 00586 svn_auth_cred_ssl_client_cert_t *ret = (svn_auth_cred_ssl_client_cert_t*)apr_pcalloc(pool, sizeof(*ret)); 00587 00588 std::string cert_file = that->askQuestion( realm, "client certificate filename: ", true, may_save ? true : false); 00589 if(cert_file == "") 00590 return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog"); 00591 00592 ret->cert_file = apr_pstrdup(pool, cert_file.c_str()); 00593 ret->may_save = that->m_maySave; 00594 *cred_p = ret; 00595 00596 return SVN_NO_ERROR; 00597 } 00598 00599 // static, callback 00600 svn_error_t* Prompter::CallbackHelpers::ssl_client_cert_pw_prompt( 00601 svn_auth_cred_ssl_client_cert_pw_t **cred_p, 00602 void *baton, 00603 const char *realm, 00604 svn_boolean_t may_save, 00605 apr_pool_t *pool) 00606 { 00607 PromptImpl *that = (PromptImpl*)baton; 00608 svn_auth_cred_ssl_client_cert_pw_t *ret = (svn_auth_cred_ssl_client_cert_pw_t*)apr_pcalloc(pool, sizeof(*ret)); 00609 00610 std::string info = that->askQuestion( realm, "client certificate passphrase: ", false, may_save ? true : false); 00611 if(info == "") 00612 return svn_error_create( SVN_ERR_RA_NOT_AUTHORIZED, NULL, "User canceled dialog"); 00613 00614 ret->password = apr_pstrdup( pool, info.c_str()); 00615 ret->may_save = that->m_maySave; 00616 *cred_p = ret; 00617 00618 return SVN_NO_ERROR; 00619 } 00620 00621 // ********************************************************************************************* 00622 // E O F 00623 // ********************************************************************************************* 00624 00625 #endif