Am 16.04.2016 um 12:09 schrieb Ben RUBSON:
Ben: have a look at how mod_rewrite accesses its own 
ap_register_rewrite_mapfunc via

So Rainer, I just quickly wrote my module, it works, many thanks for your help.

Below is my code, I just have 2 questions regarding it :
1 - do I need to "free(pw)" ?

Good question. My (Solaris) man page for getpwnam() says:

  Reentrant Interfaces
     The  getpwnam(),  getpwuid(),  getpwent(),  and  fgetpwent()
     functions use thread-specific data storage that is reused in
     each call to one of these functions by the same thread, mak-
     ing  them  safe  to use but not recommeded for multithreaded
     applications.

The Linux man page says:

The return value may point to a static area, and may be overwritten by subsequent calls to getpwent(3), getpwnam(), or getpwuid(). (Do not pass the
       returned pointer to free(3).)

And the latest standards man page of the OpenGroup says:

The getpwnam() function need not be thread-safe.
...
The application shall not modify the structure to which the return value points, nor any storage areas pointed to by pointers within the structure. The returned pointer, and pointers within the structure, might be invalidated or the structure or the storage areas might be overwritten by a subsequent call to getpwent(), getpwnam(), or getpwuid().

So you must not free the returned pointer. Two of the man pages don't guarantee thread safety so to stay on the safe side you probably better use the reentrant variants getpwnam_r() and getpwuid_r(). For those you need to allocate the storage before calling them. You can either allocate storage from the request pool (apr_palloc(r->pool, N)) or using malloc/free. Modules typically prefer pool allocation. Pool allocation doesn't need to be freed. The request pool is automatically freed at the end of each request. Even if you need the memory only shorter, if it is not many bytes it should be OK to allocate from the request pool and let it free only at the end of the request.

2 - is "key = apr_palloc(r->pool, 7)" the right method ? Doing this I want to 
avoid buffer overflow in case of uid/gid greater in length than the key parameter.

Instead of

 key = apr_palloc(r->pool, 7);
 printf(key, "%d", pw->pw_uid);

you can also use

 key = apr_psprintf(r->pool, "%d", pw->pw_uid);

And if you are not going to use more complex formatting tokens

 key = apr_ltoa(r->pool, (long)pw->pw_uid);

There's also an apr_itoa() but we might not be sure, that uid_t fits into an int.

Finally as a matter of style, I wouldn't reuse the incoming variable "key" for outgoing tasks. Instead I would declare it "const char*" as a param, and where you set

 *key = '\0';

you could also

  return "";

and then later

 return apr_ltoa(r->pool, (long)pw->pw_uid);

Everything untested ...

But as always there are many solutions that will work.

Thank you very much,

You're welcome. Nice seeing you picking up that ball so quickly. Welcome to the world of module development :) Your example was a nice one, because you don't need much clutter to realize that module.

Regards,

Rainer

#include "http_core.h"
#include "mod_rewrite.h"
#include <pwd.h>

static char *uid(request_rec *r, char *key)
{
        struct passwd *pw;
        if((pw = getpwnam(key)) == NULL)
        {
                *key = '\0';
        }
        else
        {
                key = apr_palloc(r->pool, 7);
                sprintf(key, "%d", pw->pw_uid);
        }
        return key;
}

static char *gid(request_rec *r, char *key)
{
        int uid=atoi(key);
        struct passwd *pw;
        if((pw = getpwuid(uid)) == NULL)
        {
                *key = '\0';
        }
        else
        {
                key = apr_palloc(r->pool, 7);
                sprintf(key, "%d", pw->pw_gid);
                return key;
        }
        return key;
}

static void register_hooks(apr_pool_t *pool)
{
        APR_OPTIONAL_FN_TYPE(ap_register_rewrite_mapfunc) *map_pfn_register;
        map_pfn_register = 
APR_RETRIEVE_OPTIONAL_FN(ap_register_rewrite_mapfunc);
        map_pfn_register("uid", uid);
        map_pfn_register("gid", gid);
}

AP_DECLARE_MODULE(test) = {
        STANDARD20_MODULE_STUFF,NULL,NULL,NULL,NULL,NULL,register_hooks
};

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscr...@httpd.apache.org
For additional commands, e-mail: users-h...@httpd.apache.org

Reply via email to