doauth.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. /** --- BEGIN COPYRIGHT BLOCK ---
  2. * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission.
  3. * Copyright (C) 2005 Red Hat, Inc.
  4. * All rights reserved.
  5. --- END COPYRIGHT BLOCK --- */
  6. /*
  7. * doauth.c -- CGI authentication handler -- HTTP gateway
  8. */
  9. #include "dsgw.h"
  10. #include "dbtdsgw.h"
  11. static void post_request();
  12. static void do_autherror( int rc, char *msg, char *lderrtxt,
  13. int ommitclosebutton );
  14. int main( argc, argv, env )
  15. int argc;
  16. char *argv[];
  17. {
  18. int reqmethod;
  19. reqmethod = dsgw_init( argc, argv, DSGW_METHOD_POST );
  20. post_request();
  21. exit( 0 );
  22. }
  23. static void
  24. post_request()
  25. {
  26. char *binddn, *password, *authdesturl, *encodeddn, *lderrtxt;
  27. #ifdef NOTFORNOW
  28. char *ufn;
  29. #endif
  30. LDAP *ld;
  31. int rc;
  32. int password_expiring = -1;
  33. int msgid = 0;
  34. binddn = dsgw_get_escaped_cgi_var( "escapedbinddn", "binddn",
  35. DSGW_CGIVAR_REQUIRED );
  36. encodeddn = dsgw_strdup_escaped( binddn );
  37. authdesturl = dsgw_get_cgi_var( "authdesturl", DSGW_CGIVAR_OPTIONAL );
  38. password = dsgw_get_cgi_var( "password", DSGW_CGIVAR_OPTIONAL );
  39. (void) dsgw_init_ldap( &ld, NULL, 1, 0);
  40. if ( password == NULL || strlen( password ) == 0 ) {
  41. do_autherror( 0, XP_GetClientStr( DBT_youDidNotProvidePasswd_ ),
  42. NULL, authdesturl == NULL );
  43. exit( 0 );
  44. }
  45. if( ( msgid = ldap_simple_bind( ld, binddn, password ) ) == -1 ) {
  46. rc = ldap_get_lderrno( ld, NULL, &lderrtxt );
  47. do_autherror( rc, NULL, lderrtxt, authdesturl == NULL );
  48. exit( 0 );
  49. } else {
  50. char *ckbuf;
  51. LDAPControl **ctrls = NULL;
  52. LDAPMessage *res;
  53. char *errmsg = NULL;
  54. /* Conduct password policy checks */
  55. if(( rc = ldap_result( ld, msgid, 1, NULL, &res )) == -1 ) {
  56. rc = ldap_get_lderrno( ld, NULL, &errmsg );
  57. do_autherror( rc, NULL, errmsg, authdesturl == NULL );
  58. exit( 0 );
  59. }
  60. if( ldap_parse_result( ld, res, NULL, NULL, NULL, NULL, &ctrls, 0 )
  61. != LDAP_SUCCESS ) {
  62. rc = ldap_get_lderrno( ld, NULL, &errmsg );
  63. do_autherror( rc, NULL, errmsg, authdesturl == NULL );
  64. exit( 0 );
  65. }
  66. rc = ldap_result2error( ld, res, 1 );
  67. if( rc == LDAP_SUCCESS ) {
  68. if( ctrls ) {
  69. int i;
  70. for( i = 0; ctrls[ i ] != NULL; ++i ) {
  71. if( !( strcmp( ctrls[ i ]->ldctl_oid,
  72. LDAP_CONTROL_PWEXPIRED) ) ) {
  73. /* The password has expired. Convey this information,
  74. and give the user the option to change their
  75. password immediately. */
  76. dsgw_password_expired_alert( binddn );
  77. exit( 0 );
  78. }
  79. else if( !( strcmp( ctrls[ i ]->ldctl_oid,
  80. LDAP_CONTROL_PWEXPIRING) ) ) {
  81. /* "The password is expiring in n seconds" */
  82. if( ( ctrls[ i ]->ldctl_value.bv_val != NULL ) &&
  83. ( ctrls[ i ]->ldctl_value.bv_len > 0 ) ) {
  84. password_expiring = atoi( ctrls[ i ]->ldctl_value.bv_val );
  85. }
  86. }
  87. }
  88. ldap_controls_free( ctrls );
  89. }
  90. } else if( rc == LDAP_CONSTRAINT_VIOLATION ) {
  91. rc = ldap_get_lderrno( ld, NULL, &errmsg );
  92. if( errmsg && strstr( errmsg,
  93. "Exceed password retry limit. Contact system administrator to reset" ) ) {
  94. do_autherror( rc, XP_GetClientStr(DBT_ExceedPasswordRetryContactSysAdmin_),
  95. NULL, authdesturl == NULL );
  96. } else if( errmsg && strstr( errmsg,
  97. "Exceed password retry limit. Please try later" ) ) {
  98. do_autherror( rc, XP_GetClientStr(DBT_ExceedPasswordRetryTryLater_),
  99. NULL, authdesturl == NULL );
  100. } else {
  101. do_autherror( rc, NULL, errmsg,
  102. authdesturl == NULL );
  103. }
  104. exit( 0 );
  105. } else if( rc == LDAP_INVALID_CREDENTIALS ) {
  106. if( errmsg && strstr( errmsg, "password expired" ) ) {
  107. do_autherror( rc, XP_GetClientStr(DBT_PasswordExpired_),
  108. NULL, authdesturl == NULL );
  109. } else {
  110. do_autherror( rc, NULL, errmsg,
  111. authdesturl == NULL );
  112. }
  113. exit( 0 );
  114. } else {
  115. rc = ldap_get_lderrno( ld, NULL, &errmsg );
  116. do_autherror( rc, NULL, errmsg, authdesturl == NULL );
  117. exit( 0 );
  118. }
  119. /* Construct cookie */
  120. if (( ckbuf = dsgw_mkcookie( binddn, password, gc->gc_authlifetime,
  121. &rc )) == NULL ) {
  122. switch ( rc ) {
  123. case DSGW_CKDB_CANTOPEN:
  124. do_autherror( 0, XP_GetClientStr( DBT_authDBNotOpened_ ),
  125. NULL, authdesturl == NULL );
  126. break;
  127. case DSGW_CKDB_CANTAPPEND:
  128. do_autherror( 0,
  129. XP_GetClientStr( DBT_DataCouldNotAppendToAuthDB_ ),
  130. NULL, authdesturl == NULL );
  131. break;
  132. default:
  133. do_autherror( rc, NULL, NULL, authdesturl == NULL );
  134. break;
  135. }
  136. exit( 1 );
  137. }
  138. dsgw_add_header( ckbuf );
  139. /* Construct a success message */
  140. dsgw_send_header();
  141. dsgw_emits( "<HTML>" );
  142. dsgw_head_begin();
  143. dsgw_emits( "\n"
  144. "<TITLE>Authentication Successful</TITLE>\n"
  145. "<SCRIPT LANGUAGE=\"JavaScript\">\n"
  146. "<!-- Hide from non-JavaScript browsers\n" );
  147. if ( authdesturl != NULL && strlen( authdesturl ) > 0 ) {
  148. dsgw_emitf( "var authdesturl=\"%s\";\n", authdesturl );
  149. } else {
  150. dsgw_emitf( "var authdesturl=null;\n" );
  151. }
  152. if( password_expiring != -1 ) {
  153. if ( encodeddn != NULL && strlen( encodeddn ) > 0 ) {
  154. dsgw_emitf( "var editdesturl = '%s?passwd&dn=%s&context=%s';\n",
  155. dsgw_getvp( DSGW_CGINUM_EDIT ), encodeddn, context );
  156. } else {
  157. dsgw_emitf( "var editdesturl=null;\n" );
  158. }
  159. dsgw_emits( "function editPassword()\n"
  160. "{\n"
  161. " if ( editdesturl != null ) {\n"
  162. " top.location.href = editdesturl;\n"
  163. " } else {\n"
  164. " top.close();\n"
  165. " }\n"
  166. "}\n" );
  167. }
  168. dsgw_emits( "function finishAuth()\n"
  169. "{\n"
  170. " if ( authdesturl != null ) {\n"
  171. " top.location.href = authdesturl;\n"
  172. " } else {\n"
  173. " top.close();\n"
  174. " }\n"
  175. "}\n"
  176. "var contButtons = ");
  177. dsgw_quotation_begin (QUOTATION_JAVASCRIPT_MULTILINE);
  178. dsgw_form_begin ("bForm", NULL);
  179. if( password_expiring != -1 ) {
  180. /* Create a table with 1 row and 3 columns,
  181. one column for each button... */
  182. dsgw_emitf(
  183. "\n<TABLE BORDER COLS=3 WIDTH=100%%>\n"
  184. "<TD ALIGN=CENTER>\n"
  185. "<INPUT TYPE=BUTTON NAME=\"contButton\""
  186. "VALUE=\"%s\" onClick=\"finishAuth();\">\n"
  187. "<TD ALIGN=CENTER>\n"
  188. "<INPUT TYPE=BUTTON NAME=\"editButton\""
  189. "VALUE=\"%s\" onClick=\"editPassword();\">\n"
  190. "<TD ALIGN=CENTER>",
  191. XP_GetClientStr( DBT_continue_4 ),
  192. XP_GetClientStr( DBT_EditPassword_ ));
  193. } else {
  194. dsgw_emitf(
  195. "\n<TABLE BORDER=2 WIDTH=100%%>\n"
  196. "<TD ALIGN=CENTER WIDTH=50%%>\n"
  197. "<INPUT TYPE=BUTTON NAME=\"contButton\""
  198. "VALUE=\"%s\" onClick=\"finishAuth();\">\n"
  199. "<TD ALIGN=CENTER WIDTH=50%%>",
  200. XP_GetClientStr( DBT_continue_4 ));
  201. }
  202. dsgw_emit_helpbutton( "AUTHSUCCESS" );
  203. dsgw_emits(
  204. "\n</TABLE></FORM>");
  205. dsgw_quotation_end(); dsgw_emits(";\n");
  206. dsgw_emits(
  207. "var noContButtons = ");
  208. dsgw_quotation_begin (QUOTATION_JAVASCRIPT_MULTILINE);
  209. dsgw_emits( XP_GetClientStr( DBT_ToContinue_ ));
  210. dsgw_form_begin( "bForm", NULL );
  211. dsgw_emits(
  212. "\n<TABLE BORDER=2 WIDTH=100%>"
  213. "\n<TD ALIGN=CENTER WIDTH=50%>" );
  214. dsgw_emit_homebutton();
  215. dsgw_emits( "\n<TD ALIGN=CENTER WIDTH=50%%>" );
  216. dsgw_emit_helpbutton( "AUTHSUCCESS" );
  217. dsgw_emits(
  218. "\n</TABLE></FORM>\n");
  219. dsgw_quotation_end(); dsgw_emits(";\n");
  220. dsgw_emitf(
  221. "// End hiding -->\n"
  222. "</SCRIPT>\n"
  223. "</HEAD>\n<BODY %s>\n"
  224. "<CENTER>\n"
  225. "<H3>%s</H3>\n"
  226. "</CENTER>\n",
  227. dsgw_html_body_colors,
  228. XP_GetClientStr( DBT_AuthenticationSuccessful_ )
  229. );
  230. #ifdef NOTFORNOW
  231. /* ldap_dn2ufn currectly gobble up 'dc' so don't use it for */
  232. /* now */
  233. ufn = ldap_dn2ufn( binddn );
  234. dsgw_emitf( XP_GetClientStr( DBT_YouAreNowAuthenticated_ ), ufn );
  235. #else
  236. dsgw_emitf( XP_GetClientStr( DBT_YouAreNowAuthenticated_ ), binddn );
  237. #endif
  238. dsgw_emits( "<P>\n" );
  239. #ifdef NOTFORNOW
  240. free( ufn );
  241. #endif
  242. dsgw_emitf( XP_GetClientStr( DBT_YourAuthenticationCredentialsWill_ ),
  243. gc->gc_authlifetime / 60 );
  244. dsgw_emits( XP_GetClientStr( DBT_AfterYourCredentialsExpire_ ));
  245. if( password_expiring != -1 ) {
  246. time_t cur_time, pw_exp_time_t;
  247. struct tm *pw_exp_time_tm;
  248. cur_time = dsgw_current_time();
  249. pw_exp_time_t = dsgw_time_plus_sec( cur_time, password_expiring );
  250. pw_exp_time_tm = localtime( &pw_exp_time_t );
  251. dsgw_emitf(
  252. XP_GetClientStr( DBT_ThePasswordForThisEntryWillExpire_ ),
  253. asctime( pw_exp_time_tm ));
  254. dsgw_emits( "<P>\n" );
  255. }
  256. dsgw_emits(
  257. "<P>\n"
  258. "<TR>\n"
  259. "<SCRIPT LANGUAGE=\"JavaScript\">\n"
  260. "<!-- Hide from non-JavaScript browsers\n"
  261. "if ( authdesturl != null ) {\n"
  262. " document.write( contButtons );\n"
  263. "} else {\n"
  264. " document.write( noContButtons );\n"
  265. "}\n"
  266. "// End hiding -->\n"
  267. "</SCRIPT>\n"
  268. "</BODY>\n</HTML>\n" );
  269. free( ckbuf );
  270. exit( 0 );
  271. }
  272. }
  273. static void
  274. do_autherror( int rc, char *msg, char *lderrtxt, int omitclosebutton )
  275. {
  276. dsgw_send_header();
  277. dsgw_emits( "<HTML>" );
  278. dsgw_head_begin();
  279. dsgw_emitf( "\n"
  280. "<TITLE>Authentication Error</TITLE></HEAD>\n"
  281. "<BODY %s>\n"
  282. "<CENTER>\n"
  283. "<FONT SIZE=+2>\n", dsgw_html_body_colors );
  284. dsgw_emits( XP_GetClientStr( DBT_AuthenticationFailed_ ));
  285. dsgw_emits(
  286. "</FONT>\n"
  287. "</CENTER>\n"
  288. "<P>\n");
  289. if ( msg != NULL ) {
  290. dsgw_emitf( "%s %s\n",
  291. XP_GetClientStr( DBT_AuthenticationFailedBecause_ ),
  292. msg );
  293. } else {
  294. switch ( rc ) {
  295. case LDAP_NO_SUCH_OBJECT:
  296. dsgw_emits( XP_GetClientStr( DBT_AuthEntryNotExist_ ));
  297. break;
  298. case LDAP_INAPPROPRIATE_AUTH:
  299. dsgw_emits( XP_GetClientStr( DBT_AuthEntryHasNoPassword_ ));
  300. break;
  301. case LDAP_INVALID_CREDENTIALS:
  302. dsgw_emits( XP_GetClientStr( DBT_thePasswordIsIncorrect_ ));
  303. break;
  304. case DSGW_CKDB_KEY_NOT_PRESENT:
  305. case DSGW_CKDB_DBERROR:
  306. case DSGW_CKDB_EXPIRED:
  307. case DSGW_CKDB_RNDSTRFAIL:
  308. case DSGW_CKDB_NODN:
  309. case DSGW_CKDB_CANTOPEN:
  310. case DSGW_CKDB_CANTAPPEND:
  311. dsgw_emitf( XP_GetClientStr( DBT_AuthUnexpectedError_ ), dsgw_err2string( rc ));
  312. break;
  313. default:
  314. dsgw_emitf( XP_GetClientStr( DBT_AuthUnexpectedError_ ), dsgw_ldaperr2string( rc ));
  315. break;
  316. }
  317. }
  318. if ( lderrtxt != NULL ) {
  319. dsgw_emitf( "<BR>(%s)", lderrtxt );
  320. }
  321. dsgw_emits( "<P>\n" );
  322. dsgw_form_begin( NULL, NULL );
  323. dsgw_emits(
  324. "\n"
  325. "<TABLE BORDER=2 WIDTH=100%%>\n"
  326. "<TR>\n" );
  327. if ( omitclosebutton ) {
  328. dsgw_emitf( "<TD ALIGN=CENTER WIDTH=33%%>\n"
  329. "<INPUT TYPE=BUTTON VALUE=\"%s\" onClick=\"history.back()\">\n"
  330. "<TD ALIGN=CENTER WIDTH=33%%>\n",
  331. XP_GetClientStr( DBT_Retry_ ));
  332. dsgw_emit_homebutton();
  333. dsgw_emits ( "<TD ALIGN=CENTER WIDTH=34%%>\n" );
  334. dsgw_emit_helpbutton( "AUTHPROBLEM" );
  335. } else {
  336. dsgw_emitf( "<TD ALIGN=CENTER WIDTH=33%%>\n"
  337. "<INPUT TYPE=BUTTON VALUE=\"%s\" onClick=\"history.back()\">\n"
  338. "<TD ALIGN=CENTER WIDTH=33%%>\n"
  339. "<INPUT TYPE=BUTTON VALUE=\"%s\" "
  340. "onClick=\"parent.close();\">\n"
  341. "<TD ALIGN=CENTER WIDTH=34%%>\n",
  342. XP_GetClientStr( DBT_Retry_ ),
  343. XP_GetClientStr( DBT_closeWindow_5 ));
  344. dsgw_emit_helpbutton( "AUTHPROBLEM" );
  345. }
  346. dsgw_emits( "</TABLE>\n"
  347. "</FORM>\n"
  348. "</BODY></HTML>\n" );
  349. fflush( stdout );
  350. return;
  351. }