Changeset 432

Show
Ignore:
Timestamp:
04/29/08 19:08:46 (3 months ago)
Author:
bellmich
Message:

added support for MD5 and real authentication

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libsyncml/objects/sml_auth.c

    r360 r432  
    5454        unsigned int buffersize = 0; 
    5555         
    56         if (!cred && !auth->enabled) { 
    57                 smlTrace(TRACE_INTERNAL, "Auth is disabled and no cred given"); 
    58                 auth->state = SML_NO_ERROR; 
    59         } else if (!cred && auth->enabled && auth->state != SML_AUTH_ACCEPTED) { 
    60                 smlTrace(TRACE_INTERNAL, "Auth is required"); 
    61                 auth->state = SML_ERROR_AUTH_REQUIRED; 
     56        if (!cred) 
     57        { 
     58                if (!auth->enabled) 
     59                { 
     60                        smlTrace(TRACE_INTERNAL, "Auth is disabled and no cred given"); 
     61                        auth->state = SML_NO_ERROR; 
     62                } else { 
     63                        /* auth->enabled */ 
     64                        if (auth->state != SML_AUTH_ACCEPTED) 
     65                        { 
     66                                smlTrace(TRACE_INTERNAL, "Auth is required"); 
     67                                auth->state = SML_ERROR_AUTH_REQUIRED; 
    6268                 
    63                 smlErrorSet(&error, SML_ERROR_AUTH_REQUIRED, "Auth required but not given"); 
    64                 smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error); 
    65                 smlErrorDeref(&error); 
    66         } else if ((!cred && auth->enabled && auth->state == SML_AUTH_ACCEPTED) || \ 
    67                 (cred && !auth->enabled)) { 
    68                 smlTrace(TRACE_INTERNAL, "Auth is already accepted %i", auth->enabled); 
    69                 auth->state = SML_AUTH_ACCEPTED; 
     69                                smlErrorSet(&error, SML_ERROR_AUTH_REQUIRED, "Auth required but not given"); 
     70                                smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error); 
     71                                smlErrorDeref(&error); 
     72                        } 
     73                        else 
     74                        { 
     75                                /* auth->state == SML_AUTH_ACCEPTED */ 
     76                                smlTrace(TRACE_INTERNAL, "Auth is already accepted."); 
     77                                auth->state = SML_AUTH_ACCEPTED; 
     78                        } 
     79                } 
    7080        } else { 
    71                 smlTrace(TRACE_INTERNAL, "Input is \"%s\"", cred->data); 
    72                  
    73                 switch (cred->type) { 
    74                         case SML_AUTH_TYPE_BASIC: 
    75                                  
    76                                 if (!smlBase64Decode(cred->data, &buffer, &buffersize, &error)) 
    77                                         goto error; 
    78                                  
    79                                 smlTrace(TRACE_INTERNAL, "After decode is \"%s\"", buffer); 
    80                                  
    81                                 char **arr = g_strsplit(buffer, ":", 2); 
    82                                 smlSafeCFree(&buffer); 
    83                                  
    84                                 smlTrace(TRACE_INTERNAL, "Username \"%s\", Password \"%s\"", arr[0], arr[1]); 
    85                                  
    86                                 if (auth->verifyCallback) { 
    87                                         auth->verifyCallback(auth, arr[0], arr[1], auth->verifyCallbackUserdata, &auth->state); 
     81                /* cred available */ 
     82                smlTrace(TRACE_INTERNAL, "Cred is \"%s\"", cred->data); 
     83                if (!auth->enabled) 
     84                { 
     85                        smlTrace(TRACE_INTERNAL, "Cred received but unwanted"); 
     86                        auth->state = SML_AUTH_ACCEPTED; 
     87                } else { 
     88                        /* auth->enabled */ 
     89                        if (auth->verifyCallback) 
     90                        { 
     91                                /* The callback needs the following stuff: 
     92                                 *      Chal 
     93                                 *      Cred 
     94                                 *      LocName(username) 
     95                                 */ 
     96                                if (auth->verifyCallback(session->chal, cred, 
     97                                                         smlLocationGetName(session->source), 
     98                                                         auth->verifyCallbackUserdata, &error)) 
     99                                { 
     100                                        auth->state = SML_AUTH_ACCEPTED; 
    88101                                } else { 
    89                                         smlTrace(TRACE_INTERNAL, "No verify callback set"); 
     102                                        smlErrorSet(&error, SML_ERROR_AUTH_REJECTED, 
     103                                                    "Auth rejected for username %s", 
     104                                                    smlLocationGetName(session->source)); 
     105                                        smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error); 
     106                                        smlErrorDeref(&error); 
    90107                                        auth->state = SML_ERROR_AUTH_REJECTED; 
    91108                                } 
    92                                  
    93                                 if (auth->state == SML_ERROR_AUTH_REJECTED) { 
    94                                         smlErrorSet(&error, SML_ERROR_AUTH_REJECTED, "Auth rejected for username %s", arr[0]); 
    95                                         smlSessionDispatchEvent(session, SML_SESSION_EVENT_ERROR, NULL, NULL, NULL, error); 
    96                                         smlErrorDeref(&error); 
    97                                 } 
    98                                  
    99                                 g_strfreev(arr); 
    100          
    101                                 break; 
    102                         case SML_AUTH_TYPE_MD5: 
    103                                 break; 
    104                         default: 
    105                                 smlErrorSet(&error, SML_ERROR_GENERIC, "Unknown auth format"); 
    106                                 goto error; 
     109                        } else { 
     110                                smlTrace(TRACE_INTERNAL, "No verify callback set"); 
     111                                auth->state = SML_ERROR_AUTH_REJECTED; 
     112                        } 
    107113                } 
    108114        } 
     
    132138        smlErrorDeref(&error); 
    133139        return; 
     140} 
     141 
     142char *smlAuthGetCredString( 
     143        SmlAuthType type, 
     144        const char *username, 
     145        const char *password, 
     146        const char *b64_nonce, 
     147        SmlError **error) 
     148{ 
     149        smlTrace(TRACE_ENTRY, "%s", __func__); 
     150        char *cred = NULL; 
     151 
     152        switch (type) { 
     153                case SML_AUTH_TYPE_BASIC: 
     154 
     155                        smlTrace(TRACE_INTERNAL, "%s - SML_AUTH_TYPE_BASIC", __func__); 
     156                        char *plain = g_strjoin(":", username, password, NULL); 
     157                        if (!smlBase64EncodeBinary(plain, strlen(plain), &cred, error)) 
     158                        { 
     159                                smlTrace(TRACE_INTERNAL, "%s - base64 failed", __func__); 
     160                                smlSafeCFree(&plain); 
     161                                goto error; 
     162                        } 
     163                        smlSafeCFree(&plain); 
     164 
     165                        break; 
     166                case SML_AUTH_TYPE_MD5: 
     167 
     168                        smlTrace(TRACE_INTERNAL, "%s - SML_AUTH_TYPE_MD5", __func__); 
     169                        /* How does syncml:auth-md5 works? 
     170                         * 
     171                         * base64( 
     172                         *        md5( 
     173                         *            base64( 
     174                         *                   md5( 
     175                         *                       username + ":" + password 
     176                         *                      ) 
     177                         *                  ) + 
     178                         *            ":" + nonce 
     179                         *           ) 
     180                         *       ) 
     181                         */ 
     182 
     183                        /* Let's determine the string for the comparison. */ 
     184                        ; 
     185                        char *auth = g_strjoin (":", username, password, NULL); 
     186                        unsigned char digest[16]; 
     187                        smlMD5GetDigest (auth, strlen(auth), digest); 
     188                        smlSafeCFree(&auth); 
     189                        if (!smlBase64EncodeBinary(digest, 16, &cred, error)) 
     190                        { 
     191                                smlTrace(TRACE_INTERNAL, "%s - base64 failed", __func__); 
     192                                if (cred) 
     193                                        smlSafeCFree(&cred); 
     194                                goto error; 
     195                        } 
     196                        auth = g_strjoin (":", cred, b64_nonce, NULL); 
     197                        smlSafeCFree(&cred); 
     198                        smlMD5GetDigest (auth, strlen(auth), digest); 
     199                        smlSafeCFree(&auth); 
     200                        if (!smlBase64EncodeBinary(digest, 16, &cred, error)) 
     201                        { 
     202                                smlTrace(TRACE_INTERNAL, "%s - base64 failed %s", __func__, smlErrorPrint(error)); 
     203                                if (cred) 
     204                                        smlSafeCFree(&cred); 
     205                                goto error; 
     206                        } 
     207 
     208                        break; 
     209                default: 
     210                        smlTrace(TRACE_ERROR, "%s - unknown authentication type", __func__); 
     211                        smlErrorSet(error, SML_ERROR_GENERIC, "Unknown auth format"); 
     212                        goto error; 
     213        } 
     214 
     215        smlTrace(TRACE_EXIT, "%s", __func__); 
     216        return cred; 
     217error: 
     218        smlTrace(TRACE_EXIT_ERROR, "%s - cannot create credential string"); 
     219        if (*error == NULL) 
     220                smlErrorSet(error, SML_ERROR_GENERIC, "Cannot create credential string for user %s.", 
     221                        username); 
     222        return NULL; 
     223} 
     224 
     225SmlBool smlAuthVerify(SmlChal *chal, SmlCred *cred, const char *username, const char *password, SmlError **error) 
     226{ 
     227        smlTrace(TRACE_ENTRY, "%s", __func__); 
     228 
     229        /* If no Chal is send to the client but the client offers a Cred 
     230         * then we accept it. Theoretically this is not 100% perfect if 
     231         * syncml:auth-md5 is used but if the client offers it then we 
     232         * accept it because some implementations like UIQ 3 are broken 
     233         * and implemented the protocol in a wrong way if we answer with 
     234         * error 407 and a fresh nonce. 
     235         * 
     236         * SECURITY NOTE: This part of the code makes libsyncml vulnerable 
     237         * SECURITY NOTE: against replay attacks. 
     238         * 
     239         */ 
     240        if (chal && chal->type != cred->type) 
     241        { 
     242                if (chal->type == SML_AUTH_TYPE_BASIC && 
     243                    cred->type == SML_AUTH_TYPE_MD5) 
     244                { 
     245                        /* This is an upgrade to more security. 
     246                         * So it is acceptable. 
     247                         */ 
     248                        smlTrace(TRACE_INTERNAL, "%s - replace syncml:auth-basic by syncml:auth-md5", __func__); 
     249                } else { 
     250                        /* This is a security event. */ 
     251                        smlErrorSet(error, SML_ERROR_AUTH_REJECTED, 
     252                                "The type of the authentication was changed to a lower security level."); 
     253                        goto error; 
     254                } 
     255        } 
     256        smlTrace(TRACE_INTERNAL, "%s - authentication security policy ok", __func__); 
     257 
     258        char *wanted = NULL; 
     259        switch (cred->type) { 
     260                case SML_AUTH_TYPE_BASIC: 
     261                        smlTrace(TRACE_INTERNAL, "%s - SML_AUTH_TYPE_BASIC", __func__); 
     262                        wanted = smlAuthGetCredString(SML_AUTH_TYPE_BASIC, username, password, NULL, error); 
     263                        break; 
     264                case SML_AUTH_TYPE_MD5: 
     265                        smlTrace(TRACE_INTERNAL, "%s - SML_AUTH_TYPE_MD5", __func__); 
     266                        if (chal) 
     267                                wanted = smlAuthGetCredString( 
     268                                                SML_AUTH_TYPE_MD5, 
     269                                                username, password, 
     270                                                chal->nonce_b64, error); 
     271                        else 
     272                                wanted = smlAuthGetCredString( 
     273                                                SML_AUTH_TYPE_MD5, 
     274                                                username, password, 
     275                                                "", error); 
     276                        break; 
     277                default: 
     278                        smlTrace(TRACE_ERROR, "%s - unknown authentication type", __func__); 
     279                        smlErrorSet(error, SML_ERROR_GENERIC, "Unknown auth format"); 
     280                        goto error; 
     281        } 
     282        smlTrace(TRACE_INTERNAL, "%s - credential string calculated", __func__); 
     283 
     284        /* compare the authentication string */ 
     285        if (strcmp(wanted, cred->data)) 
     286        { 
     287                smlTrace(TRACE_INTERNAL, "%s - credentials mismatch", __func__); 
     288                smlSafeCFree(&wanted); 
     289                goto error; 
     290        } 
     291        smlSafeCFree(&wanted); 
     292                         
     293        smlTrace(TRACE_EXIT, "%s", __func__); 
     294        return TRUE; 
     295error: 
     296        smlTrace(TRACE_EXIT_ERROR, "%s - auth rejected"); 
     297        if (*error == NULL) 
     298                smlErrorSet(error, SML_ERROR_AUTH_REJECTED, "Authentication rejected for username %s.", 
     299                        username); 
     300        return FALSE; 
    134301} 
    135302 
     
    210377         
    211378        if (code == SML_ERROR_AUTH_REJECTED || code == SML_ERROR_AUTH_REQUIRED) { 
    212                 reply->chal = smlTryMalloc0(sizeof(SmlChal), error); 
     379                reply->chal = smlChalNew(code, error); 
    213380                if (!reply->chal) 
    214381                        goto error_free_reply; 
    215                  
    216                 reply->chal->format = SML_FORMAT_TYPE_BASE64; 
    217                 reply->chal->type = SML_AUTH_TYPE_BASIC; 
     382                session->chal = reply->chal; 
     383                smlChalRef(session->chal); 
    218384        } 
    219385         
  • trunk/libsyncml/objects/sml_auth.h

    r101 r432  
    2323 
    2424typedef struct SmlAuthenticator SmlAuthenticator; 
    25 typedef void (* SmlAuthVerifyCb)(SmlAuthenticator *auth, const char *username, const char *password, void *userdata, SmlErrorType *reply); 
     25typedef SmlBool (* SmlAuthVerifyCb)(SmlChal *chal, SmlCred *cred, const char *username, void *userdata, SmlError **error); 
    2626 
    2727SmlAuthenticator *smlAuthNew(SmlError **error); 
     
    3434SmlBool smlAuthIsEnabled(SmlAuthenticator *auth); 
    3535 
     36/* This can be used from within the SmlAuthVerifyCb to do the authentication itself. */ 
     37SmlBool smlAuthVerify(SmlChal *chal, SmlCred *cred, const char *username, const char *password, SmlError **error); 
     38 
    3639#endif //_SML_AUTH_H_ 
  • trunk/libsyncml/objects/sml_auth_internals.h

    r68 r432  
    2222#define _SML_AUTH_INTERNALS_H_ 
    2323 
     24#include "sml_auth.h" 
     25 
    2426struct SmlAuthenticator { 
    2527        SmlErrorType state; 
     
    2931}; 
    3032 
     33char *smlAuthGetCredString( 
     34        SmlAuthType type, 
     35        const char *username, 
     36        const char *password, 
     37        const char *b64_nonce, 
     38        SmlError **error); 
     39 
    3140#endif //_SML_AUTH_INTERNALS_H_ 
  • trunk/libsyncml/parser/sml_xml_assm.c

    r427 r432  
    741741        if (!smlLocationAssemble(session->source, assm, SML_ELEMENT_SOURCE, error)) 
    742742                goto error_free_writer; 
    743          
    744         if (session->cred != NULL) { 
     743 
     744        /* The credentials must be present and calculated for the correct 
     745         * authentication schema (e.g. syncml:auth-basic or syncml:auth-md5). 
     746         */ 
     747        if (session->cred != NULL && session->cred->data != NULL) { 
    745748                if (!smlCredAssemble(session->cred, assm, error)) 
    746749                        goto error_free_writer; 
     
    11711174                                        goto error; 
    11721175                                 
    1173                                 switch (status->cred->type) { 
     1176                                switch (status->chal->type) { 
    11741177                                        case SML_AUTH_TYPE_BASIC: 
    11751178                                                if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, SML_AUTH_BASIC, error)) 
     
    11781181                                        case SML_AUTH_TYPE_MD5: 
    11791182                                                if (!_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_TYPE, SML_NAMESPACE_METINF, SML_AUTH_MD5, error)) 
     1183                                                        goto error; 
     1184                                                if (status->chal->nonce_b64 && 
     1185                                                    !_smlXmlAssemblerAddStringNS(assm, SML_ELEMENT_NEXTNONCE, SML_NAMESPACE_METINF, status->chal->nonce_b64, error)) 
    11801186                                                        goto error; 
    11811187                                                break; 
     
    12871293         
    12881294        flush_list(assm->commands); 
     1295        flush_list(assm->last_commands); 
    12891296 
    12901297        g_mutex_free(assm->mutex); 
     
    13271334        g_list_free(s2); 
    13281335         
    1329         /* Remove all commands that are complete */ 
    1330         flush_list(assm->commands); 
     1336        /* Remove all commands that are complete 
     1337         * Perhaps more correct remove all commands from the last message. 
     1338         * The actual commands are cached to support error 407 handling. 
     1339         * (AUTHENTICATION_REQUIRED) 
     1340         */ 
     1341        if (assm->last_commands) 
     1342                flush_list(assm->last_commands); 
     1343        assm->last_commands = assm->commands; 
    13311344        assm->commands = NULL; 
    13321345         
     
    17241737        functions->next_cmdref = (SmlAssemblerNextCmdRefFunction)smlXmlAssemblerNextCmdRef; 
    17251738        functions->flush = (SmlAssemblerFlushFunction)smlXmlAssemblerFlush; 
     1739        functions->restore_cmds = (SmlAssemblerRestoreCommandsFunction)smlXmlAssemblerRestoreCommands; 
    17261740         
    17271741        smlTrace(TRACE_EXIT, "%s: %p", __func__, assm); 
     
    23132327} 
    23142328 
     2329void smlXmlAssemblerRestoreCommands(SmlXmlAssembler *assm) 
     2330{ 
     2331        smlTrace(TRACE_ENTRY, "%s", __func__); 
     2332        smlAssert(assm->commands == NULL); 
     2333 
     2334        assm->commands = assm->last_commands; 
     2335        assm->last_commands = NULL; 
     2336 
     2337        smlTrace(TRACE_EXIT, "%s", __func__); 
     2338} 
     2339 
    23152340/*@}*/ 
  • trunk/libsyncml/parser/sml_xml_assm.h

    r324 r432  
    4040SmlBool smlXmlDevInfAssemble(SmlDevInf *devinf, SmlDevInfVersion version, char **data, unsigned int *size, SmlError **error); 
    4141 
     42/* This is necessary if the first message results in an error 407. 
     43 * This error means authentication required. 
     44 * After such an error the previous commands must be sent again. 
     45 */ 
     46void smlXmlAssemblerRestoreCommands(SmlXmlAssembler *assm); 
     47 
    4248#endif //_SML_XML_ASSM_H_ 
  • trunk/libsyncml/parser/sml_xml_assm_internals.h

    r324 r432  
    6262        GList *statuses; 
    6363        GList *commands; 
     64        GList *last_commands; 
    6465        GList *parent_commands; 
    6566        GList *parent_buffers; 
  • trunk/libsyncml/parser/sml_xml_parse.c

    r427 r432  
    819819        char *format = NULL; 
    820820        char *type = NULL; 
    821          
    822         SmlChal *chal = smlTryMalloc0(sizeof(SmlChal), error); 
    823         if (!chal) 
    824                 goto error; 
     821        char *nonce = NULL; 
    825822         
    826823        while (1) { 
    827824                if (!_smlXmlParserStep(parser)) { 
    828825                        smlErrorSet(error, SML_ERROR_GENERIC, "Missing nodes"); 
    829                         goto error_free_chal
     826                        goto error
    830827                } 
    831828                 
     
    835832                } else if (xmlTextReaderNodeType(parser->reader) != XML_NODE_START) { 
    836833                        smlErrorSet(error, SML_ERROR_GENERIC, "Not a start node"); 
    837                         goto error_free_chal
     834                        goto error
    838835                } 
    839836                 
    840837                if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_META)) { 
    841                         if (!_smlChalMetaParse(parser, &format, &type, &chal->nonce, error)) 
    842                                 goto error_free_chal
     838                        if (!_smlChalMetaParse(parser, &format, &type, &nonce, error)) 
     839                                goto error
    843840                } else { 
    844841                        smlErrorSet(error, SML_ERROR_GENERIC, "wrong initial node %s", xmlTextReaderConstName(parser->reader)); 
    845                         goto error_free_chal; 
    846                 } 
    847         } 
    848                  
    849         if (!format || !strcmp(format, SML_BASE64)) { 
    850                 chal->format = SML_FORMAT_TYPE_BASE64; 
    851         } else { 
     842                        goto error; 
     843                } 
     844        } 
     845                 
     846        if (format && strcmp(format, SML_BASE64)) { 
    852847                smlErrorSet(error, SML_ERROR_GENERIC, "Unknown format"); 
    853                 goto error_free_chal; 
    854         } 
    855          
     848                goto error; 
     849        } 
     850 
     851        SmlAuthType auth; 
    856852        if (!type || !strcmp(type, SML_AUTH_BASIC)) { 
    857                 chal->type = SML_AUTH_TYPE_BASIC; 
     853                auth = SML_AUTH_TYPE_BASIC; 
    858854        } else if (!strcmp(type, SML_AUTH_MD5)) { 
    859                 chal->type = SML_AUTH_TYPE_MD5; 
     855                auth = SML_AUTH_TYPE_MD5; 
    860856        } else { 
    861857                smlErrorSet(error, SML_ERROR_GENERIC, "Unknown type"); 
    862                 goto error_free_chal
    863         } 
    864          
     858                goto error
     859        } 
     860 
    865861        if (format) 
    866862                smlSafeCFree(&format); 
    867863        if (type) 
    868864                smlSafeCFree(&type); 
    869          
     865 
     866        SmlChal *chal = NULL; 
     867        if (nonce || auth == SML_AUTH_TYPE_MD5) 
     868                chal = smlChalNewFromBase64(auth, nonce, error); 
     869        else 
     870                chal = smlChalNew(auth, error); 
     871        if (!chal) 
     872                goto error; 
     873 
     874        if (nonce) 
     875                smlSafeCFree(&nonce); 
     876 
    870877        smlTrace(TRACE_EXIT, "%s: %p", __func__, chal); 
    871878        return chal; 
    872879 
    873 error_free_chal: 
    874         smlChalFree(chal); 
    875880error: 
    876881        if (format) 
     
    878883        if (type) 
    879884                smlSafeCFree(&type); 
     885        if (nonce) 
     886                smlSafeCFree(&nonce); 
    880887        smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); 
    881888        return NULL; 
     
    17591766        char *locURI = NULL; 
    17601767        SmlItem *item = NULL; 
    1761         SmlChal *chal = NULL; 
    17621768         
    17631769        /* Lets check if the next node is a command node */ 
     
    18841890                                goto error_free_status; 
    18851891                } else if (!strcmp((char *)xmlTextReaderConstName(parser->reader), SML_ELEMENT_CHAL)) { 
    1886                         chal = _smlChalParse(parser, error); 
    1887                         if (!chal) 
     1892                        (*status)->chal = _smlChalParse(parser, error); 
     1893                        if (!(*status)->chal) 
    18881894                                goto error_free_status; 
    18891895                } else { 
  • trunk/libsyncml/sml_elements.c

    r412 r432  
    581581{ 
    582582        smlTrace(TRACE_ENTRY, "%s(%d, %s, %p)", __func__, type, username, error); 
    583         char *data = NULL; 
    584         SmlFormatType format = SML_FORMAT_TYPE_BASE64; 
    585  
    586         // build plain data 
    587         if (type == SML_AUTH_TYPE_BASIC) { 
    588                 char *plain = g_strjoin(":", username, password, NULL); 
    589                 data = g_base64_encode((const unsigned char *) plain, strlen(plain)); 
    590                 smlSafeCFree(&plain); 
    591         } else if (type == SML_AUTH_TYPE_MD5) { 
    592                 char *plain = g_strjoin(":", username, password, NULL); 
    593                 unsigned char digest[16]; 
    594                 smlMD5GetDigest(plain, strlen(plain), digest); 
    595                 smlSafeCFree(&plain); 
    596                 data = smlMD5ToString(digest, NULL); 
    597                 // digest must not be freed because it is a char array 
    598         } else { 
    599                 smlErrorSet(error, SML_ERROR_GENERIC, "Unknown type - %s (%s).", type, __func__); 
    600                 goto error; 
    601         } 
    602  
    603         // the username is sometimes required as location name in the source 
    604         //     the username is readable from data     => OPTIONAL (e.g. syncml:auth-basic) 
    605         //     the username is not readable from data => REQUIRED (e.g. syncml:auth-md5) 
    606         SmlCred *cred = smlCredNew(type, format, data, username, error); 
    607         smlSafeCFree(&data); 
     583 
     584        SmlCred *cred = smlTryMalloc0(sizeof(SmlCred), error); 
     585        if (!cred) 
     586                goto error; 
     587 
     588        cred->format = SML_FORMAT_TYPE_BASE64; 
     589        cred->type = type; 
     590        cred->username = g_strdup(username); 
     591        cred->password = g_strdup(password); 
    608592 
    609593        smlTrace(TRACE_EXIT, "%s", __func__); 
    610594        return cred; 
    611595error: 
    612         if (data
    613                 smlSafeCFree(&data); 
     596        if (cred
     597                smlSafeFree((gpointer *)&cred); 
    614598        smlTrace(TRACE_EXIT_ERROR, "%s: %s", __func__, smlErrorPrint(error)); 
    615599        return NULL;     
     
    632616        cred->data = g_strdup(data); 
    633617        if (username) 
    634                 cred->locName = g_strdup(username); 
     618                cred->username = g_strdup(username); 
    635619        else 
    636                 cred->locName = NULL; 
     620                cred->username = NULL; 
    637621        cred->refCount = 1; 
    638622 
     
    642626        if (cred->data) 
    643627                smlSafeCFree(&(cred->data)); 
    644         if (cred->locName) 
    645                 smlSafeCFree(&(cred->locName)); 
     628        if (cred->username) 
     629                smlSafeCFree(&(cred->username)); 
    646630        if (cred) 
    647631                smlSafeFree((gpointer *)&cred); 
     
    650634} 
    651635 
    652 SmlCred *smlCredRef(SmlCred *cred) 
     636void smlCredRef(SmlCred *cred) 
    653637{ 
    654638        smlTrace(TRACE_ENTRY, "%s(%p)", __func__, cred); 
     
    658642         
    659643        smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, cred->refCount); 
    660         return cred; 
    661644} 
    662645 
     
    671654                if (cred->data) 
    672655                        smlSafeCFree(&(cred->data)); 
    673                 if (cred->locName) 
    674                         smlSafeCFree(&(cred->locName)); 
     656                if (cred->username) 
     657                        smlSafeCFree(&(cred->username)); 
     658                if (cred->password) 
     659                        smlSafeCFree(&(cred->password)); 
    675660                         
    676661                smlSafeFree((gpointer *)&cred); 
     
    686671} 
    687672 
     673SmlChal *smlChalNew(SmlAuthType type, SmlError **error) 
     674{ 
     675        smlTrace(TRACE_ENTRY, "%s", __func__); 
     676        SmlChal *chal = NULL; 
     677 
     678        /* allocate memory */ 
     679        smlAssert(type != SML_AUTH_TYPE_UNKNOWN); 
     680        chal = smlTryMalloc0(sizeof(SmlChal), error); 
     681        if (!chal) 
     682                goto error; 
     683        chal->refCount = 1; 
     684        chal->type = type; 
     685        chal->format = SML_FORMAT_TYPE_BASE64; 
     686 
     687        if (type == SML_AUTH_TYPE_MD5) 
     688        { 
     689                /* A nonce must be generated for this type. 
     690                 *     minimum strength:  2^128 
     691                 *     strength per byte: 2^6 - 2 > 2^5 
     692                 *     needed bytes:      128 / 5 < 130 / 5 = 26 
     693                 */ 
     694                chal->nonce_plain = smlRandStr(26, TRUE); 
     695                chal->nonce_length = 26; 
     696                if (!smlBase64EncodeBinary(chal->nonce_plain, chal->nonce_length, 
     697                                           &(chal->nonce_b64), error)) 
     698                        goto error; 
     699        } 
     700 
     701        smlTrace(TRACE_EXIT, "%s", __func__); 
     702        return chal; 
     703error: 
     704        if (chal->nonce_plain) 
     705                smlSafeCFree(&(chal->nonce_plain)); 
     706        if (chal->nonce_b64) 
     707                smlSafeCFree(&(chal->nonce_b64)); 
     708        if (chal) 
     709                smlSafeFree((gpointer *)&chal); 
     710        smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); 
     711        return NULL; 
     712} 
     713 
     714SmlChal *smlChalNewFromBinary( 
     715                SmlAuthType type, 
     716                const char *nonce, 
     717                size_t length, 
     718                SmlError **error) 
     719{ 
     720        smlTrace(TRACE_ENTRY, "%s", __func__); 
     721        SmlChal *chal = NULL; 
     722 
     723        /* only syncml:auth-md5 needs a nonce */ 
     724        smlAssert(type == SML_AUTH_TYPE_MD5); 
     725 
     726        /* allocate memory */ 
     727        chal = smlTryMalloc0(sizeof(SmlChal), error); 
     728        if (!chal) 
     729                goto error; 
     730        chal->refCount = 1; 
     731 
     732        /* copy nonce */ 
     733        chal->type = SML_AUTH_TYPE_MD5; 
     734        chal->format = SML_FORMAT_TYPE_BASE64; 
     735        chal->nonce_plain = g_strndup(nonce, length); 
     736        chal->nonce_length = length; 
     737 
     738        /* create base64 nonce */ 
     739        if (!smlBase64EncodeBinary(nonce, length, &(chal->nonce_b64), error)) 
     740                goto error; 
     741 
     742        smlTrace(TRACE_EXIT, "%s", __func__); 
     743        return chal; 
     744error: 
     745        smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); 
     746        return NULL; 
     747} 
     748 
     749SmlChal *smlChalNewFromBase64( 
     750                SmlAuthType type, 
     751                const char *nonce, 
     752                SmlError **error) 
     753{ 
     754        smlTrace(TRACE_ENTRY, "%s", __func__); 
     755        SmlChal *chal = NULL; 
     756 
     757        /* only syncml:auth-md5 needs a nonce */ 
     758        smlAssert(type == SML_AUTH_TYPE_MD5); 
     759 
     760        /* allocate memory */ 
     761        chal = smlTryMalloc0(sizeof(SmlChal), error); 
     762        if (!chal) 
     763                goto error; 
     764        chal->refCount = 1; 
     765 
     766        /* copy nonce */ 
     767        chal->type = SML_AUTH_TYPE_MD5; 
     768        chal->format = SML_FORMAT_TYPE_BASE64; 
     769        chal->nonce_b64 = g_strdup(nonce); 
     770 
     771        /* create binary nonce */ 
     772        if (!smlBase64Decode(nonce, &(chal->nonce_plain), &(chal->nonce_length), error)) 
     773                goto error; 
     774 
     775        smlTrace(TRACE_EXIT, "%s", __func__); 
     776        return chal; 
     777error: 
     778        smlTrace(TRACE_EXIT_ERROR, "%s - %s", __func__, smlErrorPrint(error)); 
     779        return NULL; 
     780} 
     781 
     782void smlChalRef(SmlChal *chal) 
     783{ 
     784        smlTrace(TRACE_ENTRY, "%s", __func__); 
     785        smlAssert(chal); 
     786         
     787        g_atomic_int_inc(&(chal->refCount)); 
     788         
     789        smlTrace(TRACE_EXIT, "%s: New refcount: %i", __func__, chal->refCount); 
     790} 
     791 
     792void smlChalUnref(SmlChal *chal) 
     793{ 
     794        smlTrace(TRACE_ENTRY, "%s", __func__); 
     795        smlAssert(chal); 
     796         
     797        if (g_atomic_int_dec_and_test(&(chal->refCount))) { 
     798                smlTrace(TRACE_INTERNAL, "Refcount == 0!"); 
     799                 
     800                if (chal->nonce_plain) 
     801                        smlSafeCFree(&(chal->nonce_plain)); 
     802 
     803                if (chal->nonce_b64) 
     804                        smlSafeCFree(&(chal->nonce_b64)); 
     805 
     806                smlSafeFree((gpointer *)&chal); 
     807        } 
     808         
     809        smlTrace(TRACE_EXIT, "%s", __func__); 
     810} 
     811 
     812/* FIXME: DEPRECATED */ 
    688813void smlChalFree(SmlChal *chal) 
    689814{ 
    690         smlTrace(TRACE_ENTRY, "%s(%p)", __func__, chal); 
    691         smlAssert(chal); 
    692          
    693         if (chal->nonce) 
    694                 smlSafeCFree(&(chal->nonce)); 
    695          
    696         smlSafeFree((gpointer *)&chal); 
    697          
    698         smlTrace(TRACE_EXIT, "%s", __func__); 
     815        smlChalUnref(chal); 
    699816} 
    700817 
  • trunk/libsyncml/sml_elements.h

    r338 r432  
    3737SmlCred *smlCredNewAuth(SmlAuthType type, const char *username, const char *password, SmlError **error); 
    3838SmlCred *smlCredNew(SmlAuthType type, SmlFormatType format, const char *data, const char*username, SmlError **error); 
    39 SmlCred *smlCredRef(SmlCred *cred); 
     39void smlCredRef(SmlCred *cred); 
    4040void smlCredUnref(SmlCred *cred); 
    4141void smlCredFree(SmlCred *cred) LIBSYNCML_DEPRECATED; /* expire date: 20090120 */ 
     
    6262void smlHeade