LCOV - code coverage report
Current view: top level - util - authtok.c (source / functions) Hit Total Coverage
Test: .coverage.total Lines: 164 209 78.5 %
Date: 2015-10-19 Functions: 20 20 100.0 %

          Line data    Source code
       1             : /*
       2             :    SSSD - auth utils
       3             : 
       4             :    Copyright (C) Simo Sorce <simo@redhat.com> 2012
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "authtok.h"
      21             : 
      22             : struct sss_auth_token {
      23             :     enum sss_authtok_type type;
      24             :     uint8_t *data;
      25             :     size_t length;
      26             : };
      27             : 
      28          28 : enum sss_authtok_type sss_authtok_get_type(struct sss_auth_token *tok)
      29             : {
      30          28 :     return tok->type;
      31             : }
      32             : 
      33          11 : size_t sss_authtok_get_size(struct sss_auth_token *tok)
      34             : {
      35          11 :     if (!tok) {
      36           0 :         return 0;
      37             :     }
      38          11 :     switch (tok->type) {
      39             :     case SSS_AUTHTOK_TYPE_PASSWORD:
      40             :     case SSS_AUTHTOK_TYPE_CCFILE:
      41             :     case SSS_AUTHTOK_TYPE_2FA:
      42             :     case SSS_AUTHTOK_TYPE_SC_PIN:
      43             :     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
      44           8 :         return tok->length;
      45             :     case SSS_AUTHTOK_TYPE_EMPTY:
      46           3 :         return 0;
      47             :     }
      48             : 
      49           0 :     return EINVAL;
      50             : }
      51             : 
      52          11 : uint8_t *sss_authtok_get_data(struct sss_auth_token *tok)
      53             : {
      54          11 :     if (!tok) {
      55           0 :         return NULL;
      56             :     }
      57          11 :     return tok->data;
      58             : }
      59             : 
      60          23 : errno_t sss_authtok_get_password(struct sss_auth_token *tok,
      61             :                                  const char **pwd, size_t *len)
      62             : {
      63          23 :     if (!tok) {
      64           0 :         return EFAULT;
      65             :     }
      66          23 :     switch (tok->type) {
      67             :     case SSS_AUTHTOK_TYPE_EMPTY:
      68           2 :         return ENOENT;
      69             :     case SSS_AUTHTOK_TYPE_PASSWORD:
      70          21 :         *pwd = (const char *)tok->data;
      71          21 :         if (len) {
      72          13 :             *len = tok->length - 1;
      73             :         }
      74          21 :         return EOK;
      75             :     case SSS_AUTHTOK_TYPE_CCFILE:
      76             :     case SSS_AUTHTOK_TYPE_2FA:
      77             :     case SSS_AUTHTOK_TYPE_SC_PIN:
      78             :     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
      79           0 :         return EACCES;
      80             :     }
      81             : 
      82           0 :     return EINVAL;
      83             : }
      84             : 
      85           5 : errno_t sss_authtok_get_ccfile(struct sss_auth_token *tok,
      86             :                                const char **ccfile, size_t *len)
      87             : {
      88           5 :     if (!tok) {
      89           0 :         return EINVAL;
      90             :     }
      91           5 :     switch (tok->type) {
      92             :     case SSS_AUTHTOK_TYPE_EMPTY:
      93           2 :         return ENOENT;
      94             :     case SSS_AUTHTOK_TYPE_CCFILE:
      95           3 :         *ccfile = (const char *)tok->data;
      96           3 :         if (len) {
      97           3 :             *len = tok->length - 1;
      98             :         }
      99           3 :         return EOK;
     100             :     case SSS_AUTHTOK_TYPE_PASSWORD:
     101             :     case SSS_AUTHTOK_TYPE_2FA:
     102             :     case SSS_AUTHTOK_TYPE_SC_PIN:
     103             :     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
     104           0 :         return EACCES;
     105             :     }
     106             : 
     107           0 :     return EINVAL;
     108             : }
     109             : 
     110          32 : static errno_t sss_authtok_set_string(struct sss_auth_token *tok,
     111             :                                       enum sss_authtok_type type,
     112             :                                       const char *context_name,
     113             :                                       const char *str, size_t len)
     114             : {
     115             :     size_t size;
     116             : 
     117          32 :     if (len == 0) {
     118           4 :         len = strlen(str);
     119             :     } else {
     120          28 :         while (len > 0 && str[len - 1] == '\0') len--;
     121             :     }
     122             : 
     123          32 :     if (len == 0) {
     124             :         /* we do not allow zero length typed tokens */
     125           0 :         return EINVAL;
     126             :     }
     127             : 
     128          32 :     size = len + 1;
     129             : 
     130          32 :     tok->data = talloc_named(tok, size, "%s", context_name);
     131          32 :     if (!tok->data) {
     132           0 :         return ENOMEM;
     133             :     }
     134          32 :     memcpy(tok->data, str, len);
     135          32 :     tok->data[len] = '\0';
     136          32 :     tok->type = type;
     137          32 :     tok->length = size;
     138             : 
     139          32 :     return EOK;
     140             : 
     141             : }
     142             : 
     143          60 : void sss_authtok_set_empty(struct sss_auth_token *tok)
     144             : {
     145          60 :     if (!tok) {
     146           0 :         return;
     147             :     }
     148          60 :     switch (tok->type) {
     149             :     case SSS_AUTHTOK_TYPE_EMPTY:
     150          47 :         return;
     151             :     case SSS_AUTHTOK_TYPE_PASSWORD:
     152             :     case SSS_AUTHTOK_TYPE_2FA:
     153             :     case SSS_AUTHTOK_TYPE_SC_PIN:
     154          10 :         safezero(tok->data, tok->length);
     155          10 :         break;
     156             :     case SSS_AUTHTOK_TYPE_CCFILE:
     157             :     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
     158           3 :         break;
     159             :     }
     160             : 
     161          13 :     tok->type = SSS_AUTHTOK_TYPE_EMPTY;
     162          13 :     talloc_zfree(tok->data);
     163          13 :     tok->length = 0;
     164             : }
     165             : 
     166          26 : errno_t sss_authtok_set_password(struct sss_auth_token *tok,
     167             :                                  const char *password, size_t len)
     168             : {
     169          26 :     sss_authtok_set_empty(tok);
     170             : 
     171          26 :     return sss_authtok_set_string(tok, SSS_AUTHTOK_TYPE_PASSWORD,
     172             :                                   "password", password, len);
     173             : }
     174             : 
     175           3 : errno_t sss_authtok_set_ccfile(struct sss_auth_token *tok,
     176             :                                const char *ccfile, size_t len)
     177             : {
     178           3 :     sss_authtok_set_empty(tok);
     179             : 
     180           3 :     return sss_authtok_set_string(tok, SSS_AUTHTOK_TYPE_CCFILE,
     181             :                                   "ccfile", ccfile, len);
     182             : }
     183             : 
     184             : static errno_t sss_authtok_set_2fa_from_blob(struct sss_auth_token *tok,
     185             :                                              const uint8_t *data, size_t len);
     186             : 
     187          13 : errno_t sss_authtok_set(struct sss_auth_token *tok,
     188             :                         enum sss_authtok_type type,
     189             :                         const uint8_t *data, size_t len)
     190             : {
     191          13 :     switch (type) {
     192             :     case SSS_AUTHTOK_TYPE_PASSWORD:
     193           3 :         return sss_authtok_set_password(tok, (const char *)data, len);
     194             :     case SSS_AUTHTOK_TYPE_CCFILE:
     195           2 :         return sss_authtok_set_ccfile(tok, (const char *)data, len);
     196             :     case SSS_AUTHTOK_TYPE_2FA:
     197           5 :         return sss_authtok_set_2fa_from_blob(tok, data, len);
     198             :     case SSS_AUTHTOK_TYPE_SC_PIN:
     199           0 :         return sss_authtok_set_sc_pin(tok, (const char*)data, len);
     200             :     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
     201           0 :         sss_authtok_set_sc_keypad(tok);
     202           0 :         return EOK;
     203             :     case SSS_AUTHTOK_TYPE_EMPTY:
     204           3 :         sss_authtok_set_empty(tok);
     205           3 :         return EOK;
     206             :     }
     207             : 
     208           0 :     return EINVAL;
     209             : }
     210             : 
     211           2 : errno_t sss_authtok_copy(struct sss_auth_token *src,
     212             :                          struct sss_auth_token *dst)
     213             : {
     214           2 :     if (!src || !dst) {
     215           0 :         return EINVAL;
     216             :     }
     217           2 :     sss_authtok_set_empty(dst);
     218             : 
     219           2 :     if (src->type == SSS_AUTHTOK_TYPE_EMPTY) {
     220           1 :         return EOK;
     221             :     }
     222             : 
     223           1 :     dst->data = talloc_memdup(dst, src->data, src->length);
     224           1 :     if (!dst->data) {
     225           0 :         return ENOMEM;
     226             :     }
     227           1 :     dst->length = src->length;
     228           1 :     dst->type = src->type;
     229             : 
     230           1 :     return EOK;
     231             : }
     232             : 
     233         135 : struct sss_auth_token *sss_authtok_new(TALLOC_CTX *mem_ctx)
     234             : {
     235             :     struct sss_auth_token *token;
     236             : 
     237         135 :     token = talloc_zero(mem_ctx, struct sss_auth_token);
     238         135 :     if (token == NULL) {
     239           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero failed.\n");
     240             :     }
     241             : 
     242         135 :     return token;
     243             : }
     244             : 
     245             : 
     246          91 : void sss_authtok_wipe_password(struct sss_auth_token *tok)
     247             : {
     248          91 :     if (!tok || tok->type != SSS_AUTHTOK_TYPE_PASSWORD) {
     249          82 :         return;
     250             :     }
     251             : 
     252           9 :     safezero(tok->data, tok->length);
     253             : }
     254             : 
     255          10 : errno_t sss_auth_unpack_2fa_blob(TALLOC_CTX *mem_ctx,
     256             :                                  const uint8_t *blob, size_t blob_len,
     257             :                                  char **fa1, size_t *_fa1_len,
     258             :                                  char **fa2, size_t *_fa2_len)
     259             : {
     260             :     size_t c;
     261             :     uint32_t fa1_len;
     262             :     uint32_t fa2_len;
     263             : 
     264          10 :     if (blob_len < 2 * sizeof(uint32_t)) {
     265           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Blob too small.\n");
     266           0 :         return EINVAL;
     267             :     }
     268             : 
     269          10 :     c = 0;
     270          10 :     SAFEALIGN_COPY_UINT32(&fa1_len, blob, &c);
     271          10 :     SAFEALIGN_COPY_UINT32(&fa2_len, blob + c, &c);
     272             : 
     273          10 :     if (blob_len != 2 * sizeof(uint32_t) + fa1_len + fa2_len) {
     274           1 :         DEBUG(SSSDBG_CRIT_FAILURE, "Blob size mismatch.\n");
     275           1 :         return EINVAL;
     276             :     }
     277             : 
     278           9 :     if (fa1_len != 0) {
     279           9 :         *fa1 = talloc_strndup(mem_ctx, (const char *) blob + c, fa1_len);
     280           9 :         if (*fa1 == NULL) {
     281           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
     282           0 :             return ENOMEM;
     283             :         }
     284             :     } else {
     285           0 :         *fa1 = NULL;
     286             :     }
     287             : 
     288           9 :     if (fa2_len != 0) {
     289           9 :         *fa2 = talloc_strndup(mem_ctx, (const char *) blob + c + fa1_len,
     290             :                               fa2_len);
     291           9 :         if (*fa2 == NULL) {
     292           0 :             DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
     293           0 :             talloc_free(*fa1);
     294           0 :             return ENOMEM;
     295             :         }
     296             :     } else {
     297           0 :         *fa2 = NULL;
     298             :     }
     299             : 
     300             :     /* Re-calculate length for the case where \0 was missing in the blob */
     301           9 :     *_fa1_len = (*fa1 == NULL) ? 0 : strlen(*fa1);
     302           9 :     *_fa2_len = (*fa2 == NULL) ? 0 : strlen(*fa2);
     303             : 
     304           9 :     return EOK;
     305             : }
     306             : 
     307           5 : static errno_t sss_authtok_set_2fa_from_blob(struct sss_auth_token *tok,
     308             :                                              const uint8_t *data, size_t len)
     309             : {
     310             :     TALLOC_CTX *tmp_ctx;
     311             :     int ret;
     312             :     char *fa1;
     313             :     size_t fa1_len;
     314             :     char *fa2;
     315             :     size_t fa2_len;
     316             : 
     317           5 :     tmp_ctx = talloc_new(NULL);
     318           5 :     if (tmp_ctx == NULL) {
     319           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_new failed.\n");
     320           0 :         ret = ENOMEM;
     321           0 :         goto done;
     322             :     }
     323             : 
     324           5 :     ret = sss_auth_unpack_2fa_blob(tmp_ctx, data, len, &fa1, &fa1_len,
     325             :                                    &fa2, &fa2_len);
     326           5 :     if (ret != EOK) {
     327           1 :         DEBUG(SSSDBG_OP_FAILURE, "sss_auth_unpack_2fa_blob failed.\n");
     328           1 :         goto done;
     329             :     }
     330             : 
     331           4 :     ret = sss_authtok_set_2fa(tok, fa1, fa1_len, fa2, fa2_len);
     332           4 :     if (ret != EOK) {
     333           0 :         DEBUG(SSSDBG_OP_FAILURE, "sss_authtok_set_2fa failed.\n");
     334           0 :         goto done;
     335             :     }
     336             : 
     337           4 :     ret = EOK;
     338             : done:
     339           5 :     talloc_free(tmp_ctx);
     340             : 
     341           5 :     if (ret != EOK) {
     342           1 :         sss_authtok_set_empty(tok);
     343             :     }
     344             : 
     345           5 :     return ret;
     346             : }
     347             : 
     348           7 : errno_t sss_authtok_get_2fa(struct sss_auth_token *tok,
     349             :                             const char **fa1, size_t *fa1_len,
     350             :                             const char **fa2, size_t *fa2_len)
     351             : {
     352             :     size_t c;
     353             :     uint32_t tmp_uint32_t;
     354             : 
     355           7 :     if (tok->type != SSS_AUTHTOK_TYPE_2FA) {
     356           2 :         return (tok->type == SSS_AUTHTOK_TYPE_EMPTY) ? ENOENT : EACCES;
     357             :     }
     358             : 
     359           5 :     if (tok->length < 2 * sizeof(uint32_t)) {
     360           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Blob too small.\n");
     361           0 :         return EINVAL;
     362             :     }
     363             : 
     364           5 :     c = 0;
     365           5 :     SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data, &c);
     366           5 :     *fa1_len = tmp_uint32_t - 1;
     367           5 :     SAFEALIGN_COPY_UINT32(&tmp_uint32_t, tok->data + c, &c);
     368           5 :     *fa2_len = tmp_uint32_t - 1;
     369             : 
     370           5 :     if (*fa1_len == 0 || *fa2_len == 0
     371           5 :             || tok->length != 2 * sizeof(uint32_t) + *fa1_len + *fa2_len + 2) {
     372           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Blob size mismatch.\n");
     373           0 :         return EINVAL;
     374             :     }
     375             : 
     376           5 :     if (tok->data[c + *fa1_len] != '\0'
     377           5 :             || tok->data[c + *fa1_len + 1 + *fa2_len] != '\0') {
     378           0 :         DEBUG(SSSDBG_CRIT_FAILURE, "Missing terminating null character.\n");
     379           0 :         return EINVAL;
     380             :     }
     381             : 
     382           5 :     *fa1 = (const char *) tok->data + c;
     383           5 :     *fa2 = (const char *) tok->data + c + *fa1_len + 1;
     384             : 
     385           5 :     return EOK;
     386             : }
     387             : 
     388          10 : errno_t sss_authtok_set_2fa(struct sss_auth_token *tok,
     389             :                             const char *fa1, size_t fa1_len,
     390             :                             const char *fa2, size_t fa2_len)
     391             : {
     392             :     int ret;
     393             :     size_t needed_size;
     394             : 
     395          10 :     if (tok == NULL) {
     396           1 :         return EINVAL;
     397             :     }
     398             : 
     399           9 :     sss_authtok_set_empty(tok);
     400             : 
     401           9 :     ret = sss_auth_pack_2fa_blob(fa1, fa1_len, fa2, fa2_len, NULL, 0,
     402             :                                  &needed_size);
     403           9 :     if (ret != EAGAIN) {
     404           4 :         DEBUG(SSSDBG_CRIT_FAILURE,
     405             :               "sss_auth_pack_2fa_blob unexpectedly returned [%d].\n", ret);
     406           4 :         return EINVAL;
     407             :     }
     408             : 
     409           5 :     tok->data = talloc_size(tok, needed_size);
     410           5 :     if (tok->data == NULL) {
     411           0 :         DEBUG(SSSDBG_OP_FAILURE, "talloc_size failed.\n");
     412           0 :         return ENOMEM;
     413             :     }
     414             : 
     415           5 :     ret = sss_auth_pack_2fa_blob(fa1, fa1_len, fa2, fa2_len, tok->data,
     416             :                                  needed_size, &needed_size);
     417           5 :     if (ret != EOK) {
     418           0 :         talloc_free(tok->data);
     419           0 :         DEBUG(SSSDBG_OP_FAILURE, "sss_auth_pack_2fa_blob failed.\n");
     420           0 :         return ret;
     421             :     }
     422           5 :     tok->length = needed_size;
     423           5 :     tok->type = SSS_AUTHTOK_TYPE_2FA;
     424             : 
     425           5 :     return EOK;
     426             : }
     427             : 
     428           5 : errno_t sss_authtok_set_sc_pin(struct sss_auth_token *tok, const char *pin,
     429             :                                size_t len)
     430             : {
     431           5 :     if (tok == NULL) {
     432           1 :         return EFAULT;
     433             :     }
     434           4 :     if (pin == NULL) {
     435           1 :         return EINVAL;
     436             :     }
     437             : 
     438           3 :     sss_authtok_set_empty(tok);
     439             : 
     440           3 :     return sss_authtok_set_string(tok, SSS_AUTHTOK_TYPE_SC_PIN,
     441             :                                   "sc_pin", pin, len);
     442             : }
     443             : 
     444           5 : errno_t sss_authtok_get_sc_pin(struct sss_auth_token *tok, const char **pin,
     445             :                                size_t *len)
     446             : {
     447           5 :     if (!tok) {
     448           1 :         return EFAULT;
     449             :     }
     450           4 :     switch (tok->type) {
     451             :     case SSS_AUTHTOK_TYPE_EMPTY:
     452           1 :         return ENOENT;
     453             :     case SSS_AUTHTOK_TYPE_SC_PIN:
     454           2 :         *pin = (const char *)tok->data;
     455           2 :         if (len) {
     456           2 :             *len = tok->length - 1;
     457             :         }
     458           2 :         return EOK;
     459             :     case SSS_AUTHTOK_TYPE_PASSWORD:
     460             :     case SSS_AUTHTOK_TYPE_CCFILE:
     461             :     case SSS_AUTHTOK_TYPE_2FA:
     462             :     case SSS_AUTHTOK_TYPE_SC_KEYPAD:
     463           1 :         return EACCES;
     464             :     }
     465             : 
     466           0 :     return EINVAL;
     467             : }
     468             : 
     469           2 : void sss_authtok_set_sc_keypad(struct sss_auth_token *tok)
     470             : {
     471           2 :     if (!tok) {
     472           1 :         return;
     473             :     }
     474           1 :     sss_authtok_set_empty(tok);
     475             : 
     476           1 :     tok->type = SSS_AUTHTOK_TYPE_SC_KEYPAD;
     477             : }

Generated by: LCOV version 1.10