svn commit: samba r7058 - in branches/SAMBA_4_0: source/lib source/web_server swat/esptest

Andrew Tridgell tridge at osdl.org
Sun May 29 02:46:49 GMT 2005


Simo,

Thanks for helping out with the esp code! Here are some comments on
your auth patch.

*) you should not use 
        #include "pwd.h"
   Instead, use 
    #include "system/passwd.h"
   as that brings in all the configure checks for different
   system authentication types.

*) The unixAuth() function you added takes only string arguments, so
    you should use espDefineStringCFunction() instead of
    espDefineCFunction(). The espDefineCFunction() call should only be
    used when one of more of the arguments is expected to be something
    other than a string. For example, the ldbSearch() function I added
    takes a hash for the list of attributes to search for, so I needed
    to use espDefineCFunction() so I could get at the hash
    elements. If you look at the other examples I've done (such as
    lpGet()) then you will see I used espDefineStringCFunction() as
    they only took string arguments. This means you can define
    esp_unixAuth() as:
         static int esp_unixAuth(struct EspRequest *ep, int argc, char **argv)
    which makes for considerably simpler code.

*) in esp_unixAuth() you explicitly set session['AUTHENTICATED'],
   session['USERNAME'] etc like this:

     mprSetPropertyValue(&ep->variables[ESP_SESSION_OBJ],
			"PRIVILEGE", mprCreateStringVar("ADMIN", 0));

   I think that is the wrong approach. Instead, I think that
   esp_UnixAuth() should return a ejs object, containing the elements
   you want. Then the esp script can do this:

     auth = esp_UnixAuth(user, pass);
     if (auth.authenticated) {
	/* user was authenticated OK as auth.username */
        session['AUTH'] = auth;
     }

   That makes for a much more flexible function. The auth code can put
   all relevent information (sid? method? token lifetime?) in the
   returned object, and it also allows for esp scripts that test
   authentication without actually becoming authenticated. For
   example, a test script might walk the samdb trying to authenticate
   as each user.

   If you have a look at how I return ldb messages in ldbSearch() you
   should see how to return general ejs objects.

   In general I think its a bad idea for our helper functions to set
   explicit variables in the ejs variable space. Instead they should
   return ejs objects, and let the script logic choose where to put
   the variable.

   I imagine you partly did this because of my comment about allowing
   the web server to check for auth on non-esp pages. I think that
   there are several ways to achieve this without tying the helper
   code to specific variables in this way. For example, we might want
   to have a /scripting/preauth.esp script that the web server always
   runs before any request (even requests for images and plain
   html). If that script produces output then that output is sent to
   the client and the page being asked for is not sent. That gives us
   a way to absolutely guarantee that every URL is authenticated,
   without requiring the error prone inclusion of a auth checking
   script at the top of every page.

*) You have a TODO like this:
   TODO: find out how to pass the real client name/address here 

   If what you want is the client IP address, then have a look at how
   the web server currently fills in request['REMOTE_HOST']. We should
   probably put this in web->input.remote_host to avoid multiple calls
   to socket_get_peer_name().

*) when a failure happens in a esp call, its a good idea to call
   espError() to set a nice error string describing what the caller
   did wrong. See the examples in esp_ldbSearch(). So for example you
   could do this:

   pwd = getpwnam(username);
   if (pwd == NULL) {
	espError(ep, "Unknown username '%s'", username);
	goto failed;
   }

   even better would be to fill in a 'reason' property on the returned
   object, and make esp_unixAuth() never return a failure.

   The problem with returning a failure from a esp helper function is
   that it immediately stops execution of the script. So if the user
   does this:

     res = ldbSearch("foo");

   then the script stops and outputs:

   ldbSearch invalid arguments Error on line 66. Offending line: res = ldbSearch("foo") 

   which is exactly what you want as giving only one argument to
   ldbSearch() is a fatal scripting error (the function must take at
   least 2 arguments). But if you do this:

     res = unixAuth("baduser", "badpass");

   then you don't want a fatal error to be thrown, what you want is
   for the script to be told that the auth failed. So you should do is
   return an object containing something like the following
   properties:

      res = unixAuth("baduser", "badpass");
      if (res.failed) {
	write("auth failed with reason " + res.reason);
      }

   To achieve that you need to return 0 (meaning success) from
   esp_unixAuth() and set the failed and reason properties on the
   returned object. We should probably create some helper functions
   similar to mprList() which make it easy to do this.


*) finally I agree with abartlet that we should not reproduce the pam
   auth code in source/web_server/. Instead, please use the generic
   auth infrastructure, or work with Andrew to add anything it needs
   if it isn't sufficient.

Sorry for such a long comment on such a simple commit! While you
probably know a lot of the above already, I thought it might be useful
for others who may wish to work with the new web server code.

Cheers, Tridge


More information about the samba-technical mailing list