[En-Nut-Discussion] HTTP password protection - better solution

Peter Sodermanns peter.sodermanns at aixcon.de
Tue Aug 29 13:23:32 CEST 2006


Hi all,

as Edwin pointed out, my first routine was buggy because of access to 
already freed objects.

Now - after several tests - I come up with a hopefully better solution.


In httpd.h I changed the declaration of AUTHINFO into fixed size in 
order to free allocated memory in NutClearAuth(). A directory name can 
have up to 255 characters, for username and password I provided 20 char, 
each.

httpd.h:
---------------------------------------------------------------------
/*
  * Authorization
  */
typedef struct _AUTHINFO AUTHINFO;

/*!
  * \struct _AUTHINFO httpd.h pro/httpd.h
  * \brief HTTP authorization information structure.
  */
struct _AUTHINFO {
     AUTHINFO *auth_next;        /*!< \brief Link to next AUTHINFO 
structure */
     char auth_dirname[256];   /*!< \brief Pathname of protected 
directory */
     char auth_login[42];     /*!< \brief Login user and password, 
separated by a colon. 20 characters each. */
};

__BEGIN_DECLS

extern int NutHttpAuthValidate(REQUEST * req);
extern int NutRegisterAuth(CONST char *dirname, CONST char *login);
extern int NutClearAuth(void);
extern int NutChangeAuth(CONST char *dirname, CONST char *oldlogin, 
CONST char *newlogin);

__END_DECLS
---------------------------------------------------------------------


The clearing function now walks through the list of authorization 
entries to the end and starts from there with freeing, since new entries 
are added at begin of the list. I tested that with as much entries as 
the heap could provide (23) and even more (113) with reduced string length.

Also I added another function NutChangeAuth() to change an existing 
entry. It takes directory, old name/password and new name/password as 
input and replaces name/password if the entry is found.

To complete user management, a function to remove a single entry would 
be useful, but that's a future task.

auth.c:
---------------------------------------------------------------------
/*!
  * \brief Clear all authorization entries.
  */
int NutClearAuth(void)
{
	AUTHINFO *idx;
	u_char n, m, count;

	/*
	 * any entries at all?
	 */
	if (authList) {
		count = 0;
		idx = authList;
		/*
		 * count entries
		 */
		while (idx) {
			count++;
			idx = idx->auth_next;
		}
		/*
		 * delete counted number of entries
		 */
		for (n=count; n>0;n--) {
			idx = authList;
			/*
			 * walk to end of list
			 */
			for (m=1; m<n;m++) {
				idx = idx->auth_next;
			}
			/*
			 * free last item
			 */
			NutHeapFree(idx);
			idx = 0;
		}
		/*
		 * indicate empty list
		 */
		authList = 0;
	}

	return 0;
}


/*!
  * \brief Change name and/or password for an existing authorization entry.
  *
  * \param dirname Name of the directory to protect.
  * \param oldlogin Current login (name:password).
  * \param newlogin Changed login (name:password).
  *
  * \return 0 on success, -1 otherwise.
  */
int NutChangeAuth(CONST char *dirname, CONST char *oldlogin, CONST char 
*newlogin)
{
     AUTHINFO *auth;

     auth = (NutHttpAuthLookup(dirname, oldlogin));
     /*
      * found that entry?
      */
     if (auth) {
         strncpy(auth->auth_login, newlogin, 41);
         return 0;
     } else {
         return -1;
     }
}


/*!
  * \brief Register an authorization entry.
  *
  * Protect a specified directory from unauthorized access.
  *
  * \warning Directories not registered by this function are
  *          accessible by anyone.
  *
  * \param dirname Name of the directory to protect.
  *                Max length of dirname is 255 characters.
  * \param login   Required login to access this directory. This
  *                string must contain a user name, followed by
  *                a colon followed by an uncrypted password.
  *                Max length of login is 41 characters.
  *
  * \return 0 on success, -1 otherwise.
  */
int NutRegisterAuth(CONST char *dirname, CONST char *login)
{
     AUTHINFO *auth;

     if ((auth = NutHeapAlloc(sizeof(AUTHINFO))) == 0)
         return -1;
     auth->auth_next = authList;
     strncpy(auth->auth_dirname, dirname, 255);
     strncpy(auth->auth_login, login, 41);
     authList = auth;

     return 0;
}
------------------------------------------------------------------

In my application this works without problem.
If you think it's ok now, too, the modification can be put into CVS.


Kind regards

            Peter


More information about the En-Nut-Discussion mailing list