doauth.c 13 KB

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