• Main Page
  • Classes
  • Files
  • File List
  • File Members

Beesnest/DcLoginManager.h

Go to the documentation of this file.
00001 /*
00002 Copyright 2007 Erez Bibi (erezbibi@users.sourceforge.net)
00003 This file is part of Beesnest.
00004 
00005 Beesnest is free software; you can redistribute it and/or modify
00006 it under the terms of the GNU General Public License as published by
00007 the Free Software Foundation; either version 2 of the License, or
00008 (at your option) any later version.
00009 
00010 Beesnest is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with Beesnest; if not, write to the Free Software
00017 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 */
00019 
00020 /* DcLoginManager.h: interface for the CdcLoginManager class. */
00021 
00022 #ifndef __CDC_LOGIN_MANAGER
00023 #define __CDC_LOGIN_MANAGER
00024 
00025 #include "DcGlobals.h"
00026 #include "DcRequest.h"
00027 #include "DcResponse.h"
00028 #include "DcHttpTime.h"
00029 #include "DcUserStatus.h"
00030 #include _GET_INCLUDE_PATH (DcCrypto.h)
00031 #include _GET_INCLUDE_PATH (DcMutex.h)
00032 #include _GET_INCLUDE_PATH (DcSemaphore.h)
00033 #include _GET_INCLUDE_PATH (DcThread.h)
00034 
00035 typedef CdcString t_code_type;  /* The one-time random code type. */
00036 
00037 /* Names... */
00038 /* For built-in after first login. */
00039 #define DC_USER_ID      "BN_UserID"         /* User ID. */
00040 #define DC_USER_CODE    "BN_RndCode"        /* User one-time random code. */
00041 #define DC_LOGIN_MSG    "BN_LoginMsg"       /* Friendly login message. */
00042 
00043 /* For challenge response - built-in or DAA. */
00044 #define DC_USER_NAME    "BN_Username"       /* User Name. */
00045 #define DC_URL          "BN_OrigURL"        /* Original requested URL. */
00046 #define DC_REALM        "BN_Realm"          /* Group of protection. */
00047 #define DC_NONCE        "BN_Nonce"          /* Server nonce. */
00048 #define DC_OPAQUE       "BN_Opaque"         /* Server other random code. */
00049 #define DC_CNONCE       "BN_Cnonce"         /* Client nonce. */
00050 #define DC_NC           "BN_NC"             /* Nonce Counter. */
00051 #define DC_RESPONSE     "BN_Response"       /* Client Response. */
00052 
00053 #define DC_LOGOUT       "BN_Logout" /* user set it to "yes" in order to logout. */
00054 
00055 /* Return valuse from the login manager. */
00056 #define DC_LM_NONE      0   /* no access restriction. */
00057 #define DC_LM_OK        1   /* access is granted. */
00058 #define DC_LM_SEND      2   /* need to send other (login/deny) page to user. */
00059 
00060 #define DC_CHL_STL_ADD  2   /* Wait a few more sec before delete stale challenge. */
00061 
00062 /**
00063  * The Log-in Manager class is a <b>static</b> class that deals with the login of
00064  * users to the system. The logging process can be done in two ways. One is the
00065  * RFC 2617 Digest Access Authentication (DAA) login process, and the other is
00066  * a server built-in login system. In addition both ways can be combined. <br>
00067  * A note should be made that the built-in login system is secure just if it is
00068  * working with SSL (or some other) encryption of the communication between the
00069  * server and the client. For full discussion of the login system see the
00070  * Login System document.
00071  * <p>
00072  * The server has a list of protected folders or files, in the Login-Manager
00073  * configuration part of the configuration files. Every file or folder that has
00074  * been set to be protected, belongs to some group of users. <br>
00075  * The groups list and their users are also listed in this section of the
00076  * configuration files (as a tree). Each group is an entry in the configuration
00077  * file, and under this entry you should write the users that belong to the
00078  * group or other groups names. <br>
00079  * The names of the login page, access-denied page and the name of the file
00080  * of user-names and passwords, are also set in this configuration section.
00081  * <p>
00082  * The Digest Access Authentication (DAA): In every request (or include) of a
00083  * protected file, the server will look for the "Authorization" header in the
00084  * request. If it finds this header it will test it against the user password.
00085  * If the server does not find this header it will send 401 response with a
00086  * WWW-Authenticate header that includes all the needed data for the client to
00087  * log in (the challenge). If the server did find the Authorization header, but
00088  * the challenge for this response was too old (stale) it will add a
00089  * "stale=true" to the challenge, so the user agent does not need to ask for
00090  * the password again. See RFC 2617 for full details.
00091  * <p>
00092  * The built-in login process starts in a similar way. The server send the exact
00093  * same challenge to the client, not in a header of 401 response, but embedded
00094  * in a special login HTML web page. the user enter his user-name and password
00095  * to an HTML form, then a (Javascript) calculation of the response should be
00096  * made on the client side, and the the same response of a DAA process should be
00097  * sent back as HTML request variables. <br>
00098  * After the first log-in the server will maintain one-time random code for this
00099  * user. This code will go back and forth between the server and the client
00100  * (different code each time), and as long as the client knows the correct code,
00101  * this user stays logged in. This process is what needs SSL for full security,
00102  * as the random code is passed in the open. (With the random code the server
00103  * sends the user an ID as well, so it can keep track of more then one user at
00104  * one time.<br>
00105  * Note that this login process require the use of some scripting language to
00106  * embed the challenge parameters in the HTML page.
00107  * <p>
00108  * There is an option to combine the two methods, and use the DAA process in the
00109  * beginning (so the user get the nice message box from the browser), but then
00110  * use the one-time code method. This will save the need of a login page with
00111  * complected Javascript, but will be more efficient than the full DAA process.
00112  * <p>
00113  * The way to tell the server which login method to use is by setting the name
00114  * (and path) of the login page in the Login-Manager configuration section. if
00115  * this file is missing the server will use DAA. <br>
00116  * Some other configuration options are: <br>
00117  * The Auto-Cookie parameter, if sets to "yes" will tell the server to insert
00118  * the one-time code and user ID to a cookie response header, every time they
00119  * exists, without the use of some scripting language. The Stale parameter will
00120  * set the time in seconds for a challenge to be valid and the Expire parameter
00121  * will set the time for a deletion of a challenge if it is not get any recent
00122  * response. In addition there should be a name (and path) of a deny page, if a
00123  * user is logged in but cannot see a certain page because he is not belong to
00124  * the correct group. If an access to a page is denied, the class will change
00125  * the page to the "Access Denied" page, You can still transfer the User Code
00126  * and User ID in this page so the user will not be logged out.
00127  * <p>
00128  * This class starts a lower priority thread to keep the challenges list clean
00129  * of old challenges. It signals this thread to scan the list after marking any
00130  * challenge for deletion, and after logging out a user (see somewhat long
00131  * explanation in the DcClean function).
00132  *
00133  * <p>
00134  * @author Erez Bibi
00135  * @version 2.0
00136  */
00137 class CdcLoginManager
00138 {
00139 private:
00140     /**
00141      * This is basically a struct to hold the challenges this class sends to
00142      * users. The challenge is standard Digest Access Authentication challenge.
00143      * See RFC 2617.
00144      */
00145     class CdcDaaChallenge
00146     {
00147     public:
00148         CdcString sRealm;       /* Identify the group this challenge is for. */
00149         CdcString sNonce;       /* Nonce For this challenge. */
00150         CdcString sOpaque;      /* This string just goes to the client and back as is. */
00151         int nNC;                /* Counter for the response (prevent replay attack). */
00152         CdcHttpTime oBuildTime; /* The time when this challenge was created. */
00153         bool isForDelete;       /* Flag to mark this challenge for deletion
00154                                     (but we can still use it for a while). */
00155         bool isCanceld;         /* This is another flag to mark challenge as void. */
00156     };
00157 
00158     /**
00159      * This is a struct to hold the response we got from the user.
00160      * The response is standard Digest Access Authentication response.
00161      * See RFC 2617.
00162      */
00163     class CdcDaaResponse
00164     {
00165     public:
00166         CdcString sUsername;    /* The username. */
00167         CdcString sRealm;       /* Identify the group this response is for. */
00168         CdcString sNonce;       /* Nonce Form the challenge. */
00169         CdcString sOpaque;      /* This string that get back as is. */
00170         CdcString sURL;         /* The requested URL. */
00171         CdcString sMethod;      /* The request method. */
00172         CdcString sQOP;         /* Quality of Protection. */
00173         CdcString sCnonce;      /* Client nonce. */
00174         CdcString sResponse;    /* The response. */
00175         CdcString sNC;          /* Response counter as string */
00176     };
00177 
00178     /**
00179      * CdcUser holds information of one user in the system. Its holds the
00180      * user-name, password, random code and a pointer to the user status object.
00181      * The class can write itself to a binary file, and create itself from a file.
00182      */
00183     class CdcUser
00184     {
00185     private:
00186         /** The user name. */
00187         CdcString sUsername;
00188         /** The user password. */
00189         CdcString sPassword;
00190         /** One time random code (for the built in login system). */
00191         t_code_type nCode;
00192         /** The last used code (for multithread requests) . */
00193         t_code_type nLastCode;
00194         /** Pointer to the user status object. */
00195         CdcUserStatus oStatus;
00196         /** True when the user is logged in. */
00197         bool isLogedin;
00198         /** Mutex for this user. */
00199         CdcMutex oMutex;
00200         /** The IP this user logged in from. */
00201         CdcString sLoginIP;
00202         /** The time of last good (random code) login. */
00203         CdcHttpTime tLastLogin;
00204 
00205     public:
00206         /** Direct constructor and default constructor. */
00207         CdcUser (const CdcString& name = EMPTY_STR,
00208             const CdcString& pass = EMPTY_STR)
00209             : sUsername (name), sPassword (pass), nCode (EMPTY_STR),
00210             isLogedin (false) {}
00211 
00212         /** Constructor from a file. */
00213         CdcUser (ifstream& inf);
00214 
00215         /** Write object to a file. */
00216         bool WriteToFile (ofstream& outf);
00217 
00218         /* Sets and gets functions. */
00219         CdcString GetUsername ()
00220         { oMutex.Lock (); CdcString temp = sUsername; oMutex.Unlock (); return temp;}
00221 
00222         void SetUsername (const CdcString& name)
00223         { oMutex.Lock (); sUsername = name; oMutex.Unlock (); }
00224 
00225         CdcString GetPassword ()
00226         { oMutex.Lock (); CdcString temp = sPassword; oMutex.Unlock (); return temp;}
00227 
00228         void SetPassword (const CdcString& pass)
00229         { oMutex.Lock (); sPassword = pass; oMutex.Unlock (); }
00230 
00231         CdcUserStatus* GetStatusObject ()
00232         { oMutex.Lock (); CdcUserStatus* temp = &oStatus; oMutex.Unlock (); return temp;}
00233 
00234         //void SetStatusObject (CdcUserStatus* pointer)
00235         //{ oMutex.Lock (); if (pStatus) delete pStatus; pStatus = pointer; oMutex.Unlock (); }
00236 
00237         t_code_type GetCode ()
00238         { oMutex.Lock (); t_code_type temp = nCode; oMutex.Unlock (); return temp;}
00239 
00240         t_code_type GetLastCode ()
00241         { oMutex.Lock (); t_code_type temp = nLastCode; oMutex.Unlock (); return temp;}
00242 
00243         void SetCode (t_code_type code)
00244         { oMutex.Lock (); nLastCode = nCode; nCode = code;
00245             tLastLogin = CdcHttpTime::GetCurrentTime (); oMutex.Unlock (); }
00246 
00247         CdcHttpTime GetLastLoginTime ()
00248         { oMutex.Lock (); CdcHttpTime temp = tLastLogin; oMutex.Unlock (); return temp;}
00249 
00250         bool IsLogedin ()
00251         { oMutex.Lock (); bool temp = isLogedin; oMutex.Unlock (); return temp;}
00252 
00253         void Logedin (bool yes)
00254         { oMutex.Lock (); isLogedin = yes; oMutex.Unlock (); }
00255 
00256         void SetIP (const CdcString& ip)
00257         { oMutex.Lock (); sLoginIP = ip; oMutex.Unlock (); }
00258 
00259         CdcString GetIP ()
00260         { oMutex.Lock (); CdcString temp = sLoginIP; oMutex.Unlock (); return temp;}
00261     };
00262 
00263 
00264     typedef vector <CdcUser*> t_users_vector;
00265     typedef map <CdcString, CdcDaaChallenge*> t_challenges_map;
00266 
00267 
00268     /** The vector of users. */
00269     static  t_users_vector vUsers;
00270 
00271     /** The map of sent challenges. */
00272     static t_challenges_map mChallenges;
00273 
00274     /** The Mutex for this map. */
00275     static CdcMutex oMapMutex;
00276 
00277     /** The name of the login HTML file (const). */
00278     static CdcString sLoginFileName;
00279 
00280     /** The name of the deny access HTML file (const).*/
00281     static CdcString sDenyFileName;
00282 
00283     /** True if the login page is empty - using DAA (const). */
00284     static bool bBuiltInLogin;
00285 
00286     /** True if need to insert ID and Random Code cookie automatically (const). */
00287     static bool bAutoCookie;
00288 
00289     /** Time limit for a nonce to become stale (const). */
00290     static int nStaleNonce;
00291 
00292     /** Time limit for a used nonce to expire (const). */
00293     static int nExpireNonce;
00294 
00295     /** Time that an old one-time-code is still good, for multithread request of
00296         protected resources (from the same page). */
00297     static int nOldCodeValid;
00298 
00299     /** This object holds the cleaning thread. */
00300     static CdcThread oCleanThread;
00301     /** Semaphore to trigger the cleaning thread. */
00302     static CdcSemaphore oStartThread;
00303     /** Flag for the thread to exit. */
00304     static bool isCleanThreadGo;
00305     /** Counter of taken challenges. */
00306     static volatile int nSomeChalTaken;
00307     /* See explanation for these 4 vars in DcClean function. */
00308 
00309     /** There is no constructor (static class). */
00310     CdcLoginManager () {}
00311 
00312     /**
00313      * Clean stale, void and old challenges. It is been called from DcClean that
00314      * runs in a separate thread. See DcClean for full explanation.
00315      */
00316     static void Clean ();
00317 
00318     /**
00319      * Make the operation to set a user as logged in. It inserts the random code
00320      * and user ID as variables in the request object if using the built-in
00321      * method. It inserts these variables as cookies if the Auto Cookies is set
00322      * (even if we are using DAA).
00323      * <p>
00324      * @param id The ID of the user to log in (index in the vector).
00325      * @param req Reference to the request object.
00326      * @param res Reference to the response object.
00327      */
00328     static void LoginUser (int id, CdcRequest& req, CdcResponse& res);
00329 
00330     /**
00331      * Insert a new random code to a cookie or request variable, if we are using
00332      * random codes. In addition this sets the user ID as a cookie or request
00333      * variable. Note that in some cases setting the user ID is redundant.
00334      * <p>
00335      * @param id The ID of the user to log in (index in the vector).
00336      * @param req Reference to the request object.
00337      * @param res Reference to the response object.
00338      */
00339     static void SetRandCode (int id, CdcRequest& req, CdcResponse& res);
00340 
00341     /**
00342      * Log out a user, cleans its object and erases login variables from the
00343      * request. If Auto Cookies is set, it erases the login cookies as well.
00344      * <p>
00345      * @param req Reference to the request object.
00346      * @param res Reference to the response object.
00347      */
00348     static void LogoutUser (CdcRequest& req, CdcResponse& res);
00349 
00350     /**
00351      * This function checks the response arrived from the client.
00352      * This is the function that implements the Digest Access Authentication
00353      * algorithm. I use it in both login methods. For the built-in just once,
00354      * when the user logs in, for DAA I call this function before sending any
00355      * protected page. See RFC 2617.
00356      * <p>
00357      * @param id The ID of this user.
00358      * @param DaaRes Reference to a Digest access authentication response.
00359      * @param stale Reference to bool, set to True if DAA response is stale.
00360      * @param wrong Reference to bool, set to True if Username/Password is wrong.
00361      * @return (bool) True if the response is correct.
00362      */
00363     static bool CheckResponse (int id, const CdcDaaResponse& DaaRes,
00364         bool& stale, bool& wrong);
00365 
00366     /**
00367      * This function checks the one time random code from the client (built-in
00368      * method)
00369      * <p>
00370      * @param id The ID of this user.
00371      * @param req Reference to the request object.
00372      * @param res Reference to the response object.
00373      * @return (bool) True if the code is correct.
00374      */
00375     static bool CheckCode (int id, CdcRequest& req, CdcResponse& res);
00376 
00377     /**
00378      * This function checks if a user is under a group. It checks it by asking
00379      * the parameters class.
00380      * <p>
00381      * @param The ID of the user (place in the vector).
00382      * @param The name of the group the user should be in.
00383      * @return (bool) True if the user is in this group.
00384      */
00385     static bool CheckGroupAccess (int id, const CdcString& group);
00386 
00387     /**
00388      * This function prepares a login page. First it generates a new challenge.
00389      * Then it either just inserts the challenge variables to the request
00390      * object variables map, and from there they will go to the login page
00391      * using a script. Or if we are using DAA, it adds an WWW-Authenticate
00392      * header to the response, and changes the response value to 401. In any way,
00393      * the ConncetionThread class will clear the previous buffer to send to the
00394      * client, and either send an empty buffer (DAA) or send the login page.
00395      * <p>
00396      * @param req Reference to the request object.
00397      * @param res Reference to the response object.
00398      * @param stale True if DAA nonce was stale.
00399      */
00400     static void BuildLoginPage (CdcRequest& req, CdcResponse& res, bool stale);
00401 
00402     /**
00403      * Find the ID (index in a vector) of the user that sent this request.
00404      * If the ID cannot be found, or if it is wrong - the function returns -1.
00405      * In addition, the function tries to find if a DAA request was made.
00406      * Note: This function returns 3 variables and an object.
00407      * <p>
00408      * @param req Reference to the request object.
00409      * @param DaaRes [output] This is a reference to an empty DAA Response
00410      *  object. The function will fill this object if some kind of response
00411      *  exists (DAA or built-in).
00412      * @param isRes [output] The function will set this reference to True if it
00413      *  finds a response to a challenge.
00414      * @param isVar [output] The function will set this reference to True if it
00415      *  finds the user ID in a request variable.
00416      * @return (int) The ID of the user or -1.
00417      */
00418     static int GetUserID (const CdcRequest& req, CdcDaaResponse& DaaRes,
00419                           bool& isRes, bool& isVar);
00420 
00421     /**
00422      * This function will try to fill a DAA response object from the HTTP
00423      * request variables. This is the response that came from a built-in login
00424      * page.
00425      * <p>
00426      * @param req Reference to the request object.
00427      * @param DaaRes Reference to the DAA response object to fill.
00428      * @return True if it finds the response nonce field (and then probably the
00429      *  entire DAA response is there).
00430      */
00431     static bool BuildResFromVar (const CdcRequest& req, CdcDaaResponse& DaaRes);
00432 
00433     /**
00434      * This function will try to fill DAA response object from the HTTP request
00435      * Authorization header. This is the response that came from a Digest Access
00436      * Authentication system.
00437      * <p>
00438      * @param req Reference to the request object.
00439      * @param DaaRes Reference to the DAA response object to fill.
00440      * @return True if it found the response Authorization header.
00441      */
00442     static bool BuildResFromHeader (const CdcRequest& req, CdcDaaResponse& DaaRes);
00443 
00444 
00445     /**
00446      * Find an ID of a user by searching the database for the username.
00447      * <p>
00448      * @param username The username to search for.
00449      * @return (int) The ID of the user or -1.
00450      */
00451     static int FindUser (const CdcString& username);
00452 
00453     /**
00454      * Find a property value in a request header field, by a property name.
00455      * <p>
00456      * @param name The property name.
00457      * @param head The header to check as CdcString.
00458      * @return (CdcString) the property value or empty string if not
00459      * found.
00460      */
00461     static CdcString GetProp (const CdcString& name, const CdcString& head);
00462 
00463 public:
00464     /**
00465      * This function loads the users database to memory, and initialize some
00466      * cryptographic features, and configuration variables.
00467      * <p>
00468      * @param file_name The name of the users database file.
00469      * @throw (CdcException) If cannot open database file, or cannot allocate
00470      * memory.
00471      */
00472     static void Load (const char* file_name);
00473 
00474     /**
00475      * This function saves the users database to a file.
00476      * <p>
00477      * @param file_name The name of the users database file.
00478      * @throw (CdcException) If cannot open database file.
00479      */
00480     static void Save (const char* file_name);
00481 
00482     /**
00483      * This is the main function of this class. it checks if the user is under
00484      * a certain group, and knows the correct password. (see the description in
00485      * the class description).
00486      * <p>
00487      * @param group The group name this page is protected by.
00488      * @param req Reference to the request object.
00489      * @param res Reference to the response object.
00490      * @param ret_code [output] A return code that can be:
00491      *  DC_LM_OK    if access is granted
00492      *  DC_LM_NONE  if the group name was empty.
00493      *  DC_LM_SEND  if need to send to user other (login/deny/DAA 401) page.
00494      * @param new_page If ret_code is DC_LM_SEND, new_page will get the relative
00495      *  path to the new page to send (or will be empty in DAA method), otherwise
00496      * it remains untouched.
00497      * @return (CdcUserStatus*) Pointer to the user status object or NULL.
00498      */
00499     static CdcUserStatus* CheckAccess (const CdcString& group, CdcRequest& req,
00500                                          CdcResponse& res, int& ret_code,
00501                                          CdcString& new_page);
00502 
00503     /**
00504      * This function should be called by CdcConnectionThread before starting
00505      * to create any response page. It checks if the user asked to be logged out,
00506      * and if so logged him out.
00507      * <p>
00508      * @param req Reference to the request object.
00509      * @param res Reference to the response object.
00510      * @return (bool) True if user logged out.
00511      */
00512     static bool CheckLogout (CdcRequest& req, CdcResponse& res);
00513 
00514     /**
00515      * Function to add a user to the class users database.
00516      * <p>
00517      * @param username The new username.
00518      * @param password The new password.
00519      * @return (bool) True if the new user added successfully.
00520      * @throw (CdcException) Out of memory exception.
00521      */
00522     static bool AddUser (const CdcString& username,
00523         const CdcString& password);
00524 
00525     /**
00526      * Function to change a user password.
00527      * <p>
00528      * @param username The username of the user.
00529      * @param old_password The old password (for identification).
00530      * @param new_password The new password.
00531      * @return (bool) True if the password has been changed successfully.
00532      */
00533     static bool ChangePassword (const CdcString& username,
00534         const CdcString& old_password, const CdcString new_password);
00535 
00536     /**
00537      * Function to remove users from the class database.
00538      * <p>
00539      * @param username The username of the user to remove.
00540      * @param password The password of the user to remove.
00541      * @return (bool) True if the user was removed successfully.
00542      */
00543     static bool RemoveUser (const CdcString& username,
00544         const CdcString& password);
00545 
00546     /**
00547      * Global function for the cleaning thread (runs in infinite loop).
00548      * <p>
00549      * The problem with the cleaning system is that the function CheckResponse
00550      * can be called many times from many different threads, as if using DAA,
00551      * this is the function that check access before sending any protected page.
00552      * In addition the running time of this function is some what long as this
00553      * is the function that do the response digest calculation on the server
00554      * side. <br>
00555      * If the cleaning thread will delete a taken challenge, the system will
00556      * crush. On the other hand, I don't want to lock the Mutex for the entire
00557      * running time of this function, because then it will mutilate other
00558      * CheckResponse functions that needs to run in other threads. There is no
00559      * reason way these functions cannot run in the same time. <br>
00560      * To solve this problem I use "Taken Challenges" global counter. When
00561      * CheckResponse is called it increases this counter by one, and waits on
00562      * the Mutex. After getting the Mutex it releases it immediately and start
00563      * working. When it is done, it decreases the counter by one. Every time a
00564      * challenge needs to be deleted, a semaphore is signaled (just before
00565      * CheckResponse returns). <br>
00566      * The cleaning thread waits on this semaphore. After getting a signal, it
00567      * sleeps for few seconds (from other reasons - the invalid challenge can
00568      * still be used by the browser, if it is a multi-frame page). After the
00569      * delay the thread calls the cleaning function. The cleaning function
00570      * checks first if the counter value is zero, if not it exits immediately.
00571      * If the counter is zero, it iterates through the challenges list and clean
00572      * every challenge that is marked for deletion, and old unused challenges.
00573      * in the beginning of every iteration cycle, it checks the counter again,
00574      * if it is not zero, it exits immediately, so CheckResponse can start
00575      * working. The uncleared challenges will have to wait for the next signal
00576      * on the semaphore.
00577      * <p>
00578      * @param pParam Pointer to bool (isCleanThreadGo) that tell the function to
00579      *  exit (close the thread).
00580      * @return (int) The return code from the thread.
00581      */
00582     friend int DcClean (void* pParam);
00583 };
00584 
00585 #endif /* __CDC_LOGIN_MANAGER */

Generated on Mon Oct 11 2010 16:23:24 for Beesnest by  doxygen 1.7.2