nph-login.cpp

00001 /*
00002  * $Id: nph-login_8cpp-source.html,v 1.1 2007/07/03 21:34:50 sebdiaz Exp $
00003  *
00004  *  Copyright (C) 1996 - 2004 Stephen F. Booth
00005  *  Copyright (C) 2001 Peter Goedtkindt
00006  *                2007 Sebastien DIAZ <sebastien.diaz@gmail.com>
00007  *  Part of the GNU cgicc library, http://www.gnu.org/software/cgicc
00008  *
00009  *  This library is free software; you can redistribute it and/or
00010  *  modify it under the terms of the GNU Lesser General Public
00011  *  License as published by the Free Software Foundation; either
00012  *  version 3 of the License, or (at your option) any later version.
00013  *
00014  *  This library is distributed in the hope that it will be useful,
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  *  Lesser General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU Lesser General Public
00020  *  License along with this library; if not, write to the Free Software
00021  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 
00022  * 
00023  */
00024 
00025 /* 
00026  * In this example, we will control the HTTPNPH header so that the user
00027  * will need to provide authentication before the cgi does something.
00028  * So far, this CGI has only been tested on IIS 5 servers and using
00029  * browsers IE 5 (Mac OS 9, MacOS X, Windows), Netscape 4.7 (Windows,
00030  * Linux, Mac), Omniweb 4 (Mac) The ask for user authentication, the
00031  * cgi issues a 403 http response code.  
00032  *
00033  * IMPORTANT: To be able to control the response type HTTP header, the
00034  * name of the cgi executable needs to start with "nph-". The cgi is
00035  * then fully responsible for the creation of _ALL_ http headers.
00036  *
00037  * IMPORTANT2: Once a valid username/password has been accepted, the
00038  * browser will send the pair with each request until you quit your
00039  * browser.  
00040  *
00041  * IMPORTANT3: On Windows servers, make certain your webserver is
00042  * configured to allow basic authentication.
00043  */
00044 
00045 #include <exception>
00046 #include <iostream>
00047 
00048 #include "cgicc/Cgicc.h"
00049 #include "cgicc/HTTPResponseHeader.h"
00050 #include "cgicc/HTMLClasses.h"
00051 
00052 using namespace std;
00053 using namespace cgicc;
00054 
00055 int
00056 main(int /*argc*/, 
00057      char ** /*argv*/)
00058 {
00059   try {
00060     Cgicc cgi;
00061     const CgiEnvironment& env = cgi.getEnvironment();
00062     string remoteuser = env.getRemoteUser();
00063     string serversw = env.getServerSoftware();
00064     string clientsw = env.getUserAgent();
00065     string authtype = env.getAuthType();
00066 
00067     if(remoteuser.empty()) {
00068       if (serversw.find("Microsoft") != string::npos 
00069           && clientsw.find("Win") != string::npos) {
00070         /*
00071           Server and client are running on Microsoft OS, so we
00072           probably can request NTLM authentication; the last test was
00073           needed to prevent IE on Mac's from using NTLM, because it
00074           seems to be broken on Macs 
00075         */
00076 
00077      cout << HTTPResponseHeader("HTTP/1.1", 401, "Unauthorized")
00078           .addHeader("WWW-Authenticate", "NTLM")
00079           .addHeader("WWW-Authenticate",  "Basic realm=\"cgicc\"");
00080   
00081         /*
00082           There is a bug in all version of Microsoft Internet Explorer
00083           at least up to 5.5 by which the NTLM authentication scheme
00084           MUST be declared first or it won't be selected. This goes
00085           against RFC 2616, which recites "A user agent MUST choose to
00086           use the strongest auth- scheme it understands" and NTLM, while
00087           broken in many ways, is still worlds stronger than Basic.
00088         */
00089       }
00090       else {
00091         // we're not chatting fully MS: only support basic
00092         cout << HTTPResponseHeader("HTTP/1.1", 401, "Unauthorized")
00093           .addHeader("WWW-Authenticate", "Basic realm=\"cgicc\"");
00094       }
00095       // do not add html data: browsers should not display this anyway
00096       //  they should request user/password from the user and re-emit
00097       //  the same request, only with the authentification info added
00098       //  to the request 
00099       cout << HTMLDoctype(HTMLDoctype::eStrict) << endl;
00100       cout << html().set("lang", "EN").set("dir", "LTR") << endl;
00101     
00102       cout << head() << endl;
00103       cout << title("401 Authorization Required")  << endl;
00104       cout << head() << endl;
00105     
00106       cout << body() << endl;
00107       cout << h1("401 Authorization Required") << endl;
00108       cout << p() << "This server could not verify that you are "
00109            << "authorized to access the document requested. Either you "
00110            << "supplied the wrong credentials (e.g., bad password), or "
00111            << "your browser doesn't understand how to supply the "
00112            << "credentials required." << p();
00113 
00114       cout << hr() << endl;
00115       cout << address() << "GNU cgicc \"server\" version " << cgi.getVersion()
00116            << address() << endl;
00117 
00118       return 0;
00119     }
00120   
00121     // Output the HTTP headers 200 OK header for an HTML document, and
00122     // the HTML 4.0 DTD info
00123     cout << HTTPResponseHeader(env.getServerProtocol(), 200 ,"OK")
00124       .addHeader("Content-Type", "text/html");
00125     cout << HTMLDoctype(HTMLDoctype::eStrict) << endl;
00126     cout << html().set("lang", "EN").set("dir", "LTR") << endl;
00127 
00128     // Set up the page's header and title.
00129     cout << head() << endl;
00130     cout << title() << "GNU cgicc v" << cgi.getVersion() << title() << endl;
00131     cout << head() << endl;
00132     
00133     // Start the HTML body
00134     cout << body() << endl;
00135 
00136     // Print out a message
00137     cout << "Hello " << env.getRemoteUser() 
00138          << " your login was accepted" << br() << endl;
00139     cout << "You were authenticated using authentication scheme : " 
00140          << env.getAuthType() << br() << endl;
00141     cout << "Your server software is :" << serversw << br() << endl;
00142     cout << "Your browser software is :" << clientsw << br() << endl;
00143     // Close the document
00144     cout << body() << html();
00145 
00146 
00147   }
00148   
00149   catch(const exception& e) {
00150     // handle error condition
00151   }
00152   
00153   return 0;
00154 }

Generated on Tue Jul 3 15:44:29 2007 for GNUCgicc by  doxygen 1.5.1