$Revision$ $Date$ Digest Body Parser Purpose of this parser is to parse digest response. The parser can be found under parser/digest subdirectory. There might be several header fields containing digest response, for example Proxy-Authorization or WWW-Authorization. The parser can be used for all of them. The parser is not called automatically when by the main parser. It is your responsibility to call the parser when you want a digest response to be parsed. Main function is parse_credentials defined in digest.c. The function accepts one parameter which is header field to be parsed. As result the function will create an instance of auth_body_t structure which will represent the parsed digest credentials. Pointer to the structure will be put in parsed field of the hdr_field structure representing the parsed header field. It will be freed when the whole message is being destroyed. The digest parser contains 32-bit digest parameter parser. The parser was in detail described in section Header Field Name Parser. See that section for more details about the digest parameter parser algorithm, they work in the same way. Description of digest related structures follows: typedef struct auth_body { /* This is pointer to header field containing * parsed authorized digest credentials. This * pointer is set in sip_msg->{authorization,proxy_auth} * hooks. * * This is necessary for functions called after * {www,proxy}_authorize, these functions need to know * which credentials are authorized and they will simply * look into * sip_msg->{authorization,proxy_auth}->parsed->authorized */ struct hdr_field* authorized; dig_cred_t digest; /* Parsed digest credentials */ unsigned char stale; /* Flag is set if nonce is stale */ int nonce_retries; /* How many times the nonce was used */ } auth_body_t; This is the "main" structure. Pointer to the structure will be stored in parsed field of hdr_field structure. Detailed description of its fields follows: authorized - This is a hook to header field containing authorized credentials. A SIP message may contain several credentials. They are distinguished using realm parameter. When the server is trying to authorize the message, it must first find credentials with corresponding realm and than authorize the credentials. To authorize credentials server calculates response string and if the string matches to response string contained in the credentials, credentials are authorized (in fact it means that the user specified in the credentials knows password, nothing more, nothing less). It would be good idea to remember which credentials contained in the message are authorized, there might be other functions interested in knowing which credentials are authorized. That is what is this field for. A function that successfully authorized credentials (currently there is only one such function in the server, it is function authorize in auth module) will put pointer to header field containing the authorized credentials in this field. Because there might be several header field containing credentials, the pointer will be put in authorized field in the first header field in the message containing credentials. That means that it will be either header field whose pointer is in www_auth or proxy_auth field of sip_msg structure representing the message. When a function wants to find authorized credentials, it will simply look in msg->www_auth->parsed->authorized or msg->proxy_auth->parsed->authorized, where msg is variable containing pointer to sip_msg structure. To simplify the task of saving and retrieving pointer to authorized credentials, there are two convenience functions defined in digest.c file. They will be described later. digest - Structure containing parsed digest credentials. The structure will be described in detail later. stale - This field will be set to 1 if the server received a stale nonce. Next time when the server will be sending another challenge, it will use "stale=true" parameter. "stale=true" indicates to the client that username and password used to calculate response were correct, but nonce was stale. The client should recalculate response with the same username and password (without disturbing user) and new nonce. For more details see RFC2617. nonce_retries - This fields indicates number of authorization attempts with same nonce. /* * Errors returned by check_dig_cred */ typedef enum dig_err { E_DIG_OK = 0, /* Everything is OK */ E_DIG_USERNAME = 1, /* Username missing */ E_DIG_REALM = 2, /* Realm missing */ E_DIG_NONCE = 4, /* Nonce value missing */ E_DIG_URI = 8, /* URI missing */ E_DIG_RESPONSE = 16, /* Response missing */ E_DIG_CNONCE = 32, /* CNONCE missing */ E_DIG_NC = 64, /* Nonce-count missing */ } dig_err_t; This is enum of all possible errors returned by check_dig_cred function. E_DIG_OK - No error found. E_DIG_USERNAME - Username parameter missing in digest response. E_DIG_REALM - Realm parameter missing in digest response. E_DIG_NONCE - Nonce parameter missing in digest response. E_DIG_URI - Uri parameter missing in digest response. E_DIG_RESPONSE - Response parameter missing in digest response. E_DIG_CNONCE - Cnonce parameter missing in digest response. E_DIG_NC - Nc parameter missing in digest response. /* Type of algorithm used */ typedef enum alg { ALG_UNSPEC = 0, /* Algorithm parameter not specified */ ALG_MD5 = 1, /* MD5 - default value*/ ALG_MD5SESS = 2, /* MD5-Session */ ALG_OTHER = 4 /* Unknown */ } alg_t; This is enum of recognized algorithm types. (See description of algorithm structure for more details). ALG_UNSPEC - Algorithm was not specified in digest response. ALG_MD5 - "algorithm=MD5" was found in digest response. ALG_MD5SESS - "algorithm=MD5-Session" was found in digest response. ALG_OTHER - Unknown algorithm parameter value was found in digest response. /* Quality Of Protection used */ typedef enum qop_type { QOP_UNSPEC = 0, /* QOP parameter not present in response */ QOP_AUTH = 1, /* Authentication only */ QOP_AUTHINT = 2, /* Authentication with integrity checks */ QOP_OTHER = 4 /* Unknown */ } qop_type_t; This enum lists all recognized qop parameter values. QOP_UNSPEC - qop parameter was not found in digest response. QOP_AUTH - "qop=auth" was found in digest response. QOP_AUTHINT - "qop=auth-int" was found in digest response. QOP_OTHER - Unknown qop parameter value was found in digest response. /* Algorithm structure */ struct algorithm { str alg_str; /* The original string representation */ alg_t alg_parsed; /* Parsed value */ }; The structure represents "algorithm" parameter of digest response. Description of fields follows: alg_str - Algorithm parameter value as string. alg_parsed - Parsed algorithm parameter value. /* QOP structure */ struct qp { str qop_str; /* The original string representation */ qop_type_t qop_parsed; /* Parsed value */ }; This structure represents "qop" parameter of digest response. Description of fields follows: qop_str - Qop parameter value as string. qop_parsed - Parsed "qop" parameter value. /* * Parsed digest credentials */ typedef struct dig_cred { str username; /* Username */ str realm; /* Realm */ str nonce; /* Nonce value */ str uri; /* URI */ str response; /* Response string */ str algorithm; /* Algorithm in string representation */ struct algorithm alg; /* Type of algorithm used */ str cnonce; /* Cnonce value */ str opaque; /* Opaque data string */ struct qp qop; /* Quality Of Protection */ str nc; /* Nonce count parameter */ } dig_cred_t; This structure represents set of digest credentials parameters. Description of field follows: username - Value of "username" parameter. realm - Value of "realm" parameter. nonce - Value of "nonce" parameter. uri - Value of "uri" parameter. response - Value of "response" parameter. algorithm - Value of "algorithm" parameter as string. alg - Parsed value of "algorithm" parameter. cnonce - Value of "cnonce" parameter. opaque - Value of "opaque" parameter. qop - Value of "qop" parameter. nc - Value of "nc" parameter.
Other Functions Of the Digest Parser There are some other mainly convenience functions defined in the parser. The function will be in detail described in this section. All the functions are defined in digest.c file. dig_err_t check_dig_cred dig_cred_t* _c This function performs some basic sanity check over parsed digest credentials. The following conditions must be met for the checks to be successful: There must be non-empty "username" parameter in the credentials. There must be non-empty "realm" parameter in the credentials. There must be non-empty "nonce" parameter in the credentials. There must be non-empty "uri" parameter in the credentials. There must be non-empty "response" parameter in the credentials. If qop parameter is set to QOP_AUTH or QOP_AUTHINT, then there must be also non-empty "cnonce" and "nc" parameters in the digest. It is recommended to call check_dig_cred before you try to authorize the credentials. If the function fails, there is no need to try to authorize the credentials because the authorization will fail for sure. int mark_authorized_cred struct sip_msg* _m struct hdr_field* _h This is convenience function. The function saves pointer to the authorized credentials. For more info see description of authorized field in auth_body structure. int get_authorized_cred struct sip_msg* _m struct hdr_field** _h This is convenience function. The function will retrieve pointer to authorized credentials previously saved using mark_authorized_cred function. If there is no such credentials, 0 will be stored in variable pointed to by the second parameter. The function returns always zero. For more information see description of authorized field in auth_body structure.