00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "internal.h"
00024
00040 int
00041 gsasl_client_listmech (Gsasl * ctx, char *out, size_t * outlen)
00042 {
00043 char *tmp;
00044 int rc;
00045
00046 rc = gsasl_client_mechlist (ctx, &tmp);
00047
00048 if (rc == GSASL_OK)
00049 {
00050 size_t tmplen = strlen (tmp);
00051
00052 if (tmplen >= *outlen)
00053 {
00054 free (tmp);
00055 return GSASL_TOO_SMALL_BUFFER;
00056 }
00057
00058 if (out)
00059 strcpy (out, tmp);
00060 *outlen = tmplen + 1;
00061 free (tmp);
00062 }
00063
00064 return rc;
00065 }
00066
00082 int
00083 gsasl_server_listmech (Gsasl * ctx, char *out, size_t * outlen)
00084 {
00085 char *tmp;
00086 int rc;
00087
00088 rc = gsasl_server_mechlist (ctx, &tmp);
00089
00090 if (rc == GSASL_OK)
00091 {
00092 size_t tmplen = strlen (tmp);
00093
00094 if (tmplen >= *outlen)
00095 {
00096 free (tmp);
00097 return GSASL_TOO_SMALL_BUFFER;
00098 }
00099
00100 if (out)
00101 strcpy (out, tmp);
00102 *outlen = tmplen + 1;
00103 free (tmp);
00104 }
00105
00106 return rc;
00107 }
00108
00109 static int
00110 _gsasl_step (Gsasl_session * sctx,
00111 const char *input, size_t input_len,
00112 char *output, size_t * output_len)
00113 {
00114 char *tmp;
00115 size_t tmplen;
00116 int rc;
00117
00118 rc = gsasl_step (sctx, input, input_len, &tmp, &tmplen);
00119
00120 if (rc == GSASL_OK || rc == GSASL_NEEDS_MORE)
00121 {
00122 if (tmplen >= *output_len)
00123 {
00124 free (tmp);
00125
00126 return GSASL_TOO_SMALL_BUFFER;
00127 }
00128
00129 if (output)
00130 memcpy (output, tmp, tmplen);
00131 *output_len = tmplen;
00132 free (tmp);
00133 }
00134
00135 return rc;
00136 }
00137
00160 int
00161 gsasl_client_step (Gsasl_session * sctx,
00162 const char *input,
00163 size_t input_len, char *output, size_t * output_len)
00164 {
00165 return _gsasl_step (sctx, input, input_len, output, output_len);
00166 }
00167
00190 int
00191 gsasl_server_step (Gsasl_session * sctx,
00192 const char *input,
00193 size_t input_len, char *output, size_t * output_len)
00194 {
00195 return _gsasl_step (sctx, input, input_len, output, output_len);
00196 }
00197
00198 static int
00199 _gsasl_step64 (Gsasl_session * sctx,
00200 const char *b64input, char *b64output, size_t b64output_len)
00201 {
00202 char *tmp;
00203 int rc;
00204
00205 rc = gsasl_step64 (sctx, b64input, &tmp);
00206
00207 if (rc == GSASL_OK || rc == GSASL_NEEDS_MORE)
00208 {
00209 if (b64output_len <= strlen (tmp))
00210 {
00211 free (tmp);
00212
00213 return GSASL_TOO_SMALL_BUFFER;
00214 }
00215
00216 if (b64output)
00217 strcpy (b64output, tmp);
00218 free (tmp);
00219 }
00220
00221 return rc;
00222 }
00223
00238 int
00239 gsasl_client_step_base64 (Gsasl_session * sctx,
00240 const char *b64input,
00241 char *b64output, size_t b64output_len)
00242 {
00243 return _gsasl_step64 (sctx, b64input, b64output, b64output_len);
00244 }
00245
00260 int
00261 gsasl_server_step_base64 (Gsasl_session * sctx,
00262 const char *b64input,
00263 char *b64output, size_t b64output_len)
00264 {
00265 return _gsasl_step64 (sctx, b64input, b64output, b64output_len);
00266 }
00267
00277 void
00278 gsasl_client_finish (Gsasl_session * sctx)
00279 {
00280 gsasl_finish (sctx);
00281 }
00282
00292 void
00293 gsasl_server_finish (Gsasl_session * sctx)
00294 {
00295 gsasl_finish (sctx);
00296 }
00297
00306 Gsasl *
00307 gsasl_client_ctx_get (Gsasl_session * sctx)
00308 {
00309 return sctx->ctx;
00310 }
00311
00326 void
00327 gsasl_client_application_data_set (Gsasl_session * sctx,
00328 void *application_data)
00329 {
00330 gsasl_appinfo_set (sctx, application_data);
00331 }
00332
00347 void *
00348 gsasl_client_application_data_get (Gsasl_session * sctx)
00349 {
00350 return gsasl_appinfo_get (sctx);
00351 }
00352
00361 Gsasl *
00362 gsasl_server_ctx_get (Gsasl_session * sctx)
00363 {
00364 return sctx->ctx;
00365 }
00366
00381 void
00382 gsasl_server_application_data_set (Gsasl_session * sctx,
00383 void *application_data)
00384 {
00385 gsasl_appinfo_set (sctx, application_data);
00386 }
00387
00402 void *
00403 gsasl_server_application_data_get (Gsasl_session * sctx)
00404 {
00405 return gsasl_appinfo_get (sctx);
00406 }
00407
00421 int
00422 gsasl_randomize (int strong, char *data, size_t datalen)
00423 {
00424 if (strong)
00425 return gsasl_random (data, datalen);
00426 return gsasl_nonce (data, datalen);
00427 }
00428
00437 Gsasl *
00438 gsasl_ctx_get (Gsasl_session * sctx)
00439 {
00440 return sctx->ctx;
00441 }
00442
00461 int
00462 gsasl_encode_inline (Gsasl_session * sctx,
00463 const char *input, size_t input_len,
00464 char *output, size_t * output_len)
00465 {
00466 char *tmp;
00467 size_t tmplen;
00468 int res;
00469
00470 res = gsasl_encode (sctx, input, input_len, &tmp, &tmplen);
00471 if (res == GSASL_OK)
00472 {
00473 if (*output_len < tmplen)
00474 return GSASL_TOO_SMALL_BUFFER;
00475 *output_len = tmplen;
00476 memcpy (output, tmp, tmplen);
00477 free (output);
00478 }
00479
00480 return res;
00481 }
00482
00501 int
00502 gsasl_decode_inline (Gsasl_session * sctx,
00503 const char *input, size_t input_len,
00504 char *output, size_t * output_len)
00505 {
00506 char *tmp;
00507 size_t tmplen;
00508 int res;
00509
00510 res = gsasl_decode (sctx, input, input_len, &tmp, &tmplen);
00511 if (res == GSASL_OK)
00512 {
00513 if (*output_len < tmplen)
00514 return GSASL_TOO_SMALL_BUFFER;
00515 *output_len = tmplen;
00516 memcpy (output, tmp, tmplen);
00517 free (output);
00518 }
00519
00520 return res;
00521 }
00522
00536 void
00537 gsasl_application_data_set (Gsasl * ctx, void *appdata)
00538 {
00539 ctx->application_hook = appdata;
00540 }
00541
00555 void *
00556 gsasl_application_data_get (Gsasl * ctx)
00557 {
00558 return ctx->application_hook;
00559 }
00560
00574 void
00575 gsasl_appinfo_set (Gsasl_session * sctx, void *appdata)
00576 {
00577 sctx->application_data = appdata;
00578 }
00579
00593 void *
00594 gsasl_appinfo_get (Gsasl_session * sctx)
00595 {
00596 return sctx->application_data;
00597 }
00598
00611 const char *
00612 gsasl_server_suggest_mechanism (Gsasl * ctx, const char *mechlist)
00613 {
00614 return NULL;
00615 }
00616
00631 void
00632 gsasl_client_callback_authentication_id_set (Gsasl * ctx,
00633 Gsasl_client_callback_authentication_id
00634 cb)
00635 {
00636 ctx->cbc_authentication_id = cb;
00637 }
00638
00651 Gsasl_client_callback_authentication_id
00652 gsasl_client_callback_authentication_id_get (Gsasl * ctx)
00653 {
00654 return ctx ? ctx->cbc_authentication_id : NULL;
00655 }
00656
00671 void
00672 gsasl_client_callback_authorization_id_set (Gsasl * ctx,
00673 Gsasl_client_callback_authorization_id
00674 cb)
00675 {
00676 ctx->cbc_authorization_id = cb;
00677 }
00678
00691 Gsasl_client_callback_authorization_id
00692 gsasl_client_callback_authorization_id_get (Gsasl * ctx)
00693 {
00694 return ctx ? ctx->cbc_authorization_id : NULL;
00695 }
00696
00711 void
00712 gsasl_client_callback_password_set (Gsasl * ctx,
00713 Gsasl_client_callback_password cb)
00714 {
00715 ctx->cbc_password = cb;
00716 }
00717
00718
00731 Gsasl_client_callback_password
00732 gsasl_client_callback_password_get (Gsasl * ctx)
00733 {
00734 return ctx ? ctx->cbc_password : NULL;
00735 }
00736
00751 void
00752 gsasl_client_callback_passcode_set (Gsasl * ctx,
00753 Gsasl_client_callback_passcode cb)
00754 {
00755 ctx->cbc_passcode = cb;
00756 }
00757
00758
00771 Gsasl_client_callback_passcode
00772 gsasl_client_callback_passcode_get (Gsasl * ctx)
00773 {
00774 return ctx ? ctx->cbc_passcode : NULL;
00775 }
00776
00793 void
00794 gsasl_client_callback_pin_set (Gsasl * ctx, Gsasl_client_callback_pin cb)
00795 {
00796 ctx->cbc_pin = cb;
00797 }
00798
00799
00812 Gsasl_client_callback_pin
00813 gsasl_client_callback_pin_get (Gsasl * ctx)
00814 {
00815 return ctx ? ctx->cbc_pin : NULL;
00816 }
00817
00835 void
00836 gsasl_client_callback_service_set (Gsasl * ctx,
00837 Gsasl_client_callback_service cb)
00838 {
00839 ctx->cbc_service = cb;
00840 }
00841
00854 Gsasl_client_callback_service
00855 gsasl_client_callback_service_get (Gsasl * ctx)
00856 {
00857 return ctx ? ctx->cbc_service : NULL;
00858 }
00859
00875 void
00876 gsasl_client_callback_anonymous_set (Gsasl * ctx,
00877 Gsasl_client_callback_anonymous cb)
00878 {
00879 ctx->cbc_anonymous = cb;
00880 }
00881
00894 Gsasl_client_callback_anonymous
00895 gsasl_client_callback_anonymous_get (Gsasl * ctx)
00896 {
00897 return ctx ? ctx->cbc_anonymous : NULL;
00898 }
00899
00914 void
00915 gsasl_client_callback_qop_set (Gsasl * ctx, Gsasl_client_callback_qop cb)
00916 {
00917 ctx->cbc_qop = cb;
00918 }
00919
00932 Gsasl_client_callback_qop
00933 gsasl_client_callback_qop_get (Gsasl * ctx)
00934 {
00935 return ctx ? ctx->cbc_qop : NULL;
00936 }
00937
00955 void
00956 gsasl_client_callback_maxbuf_set (Gsasl * ctx,
00957 Gsasl_client_callback_maxbuf cb)
00958 {
00959 ctx->cbc_maxbuf = cb;
00960 }
00961
00974 Gsasl_client_callback_maxbuf
00975 gsasl_client_callback_maxbuf_get (Gsasl * ctx)
00976 {
00977 return ctx ? ctx->cbc_maxbuf : NULL;
00978 }
00979
00995 void
00996 gsasl_client_callback_realm_set (Gsasl * ctx, Gsasl_client_callback_realm cb)
00997 {
00998 ctx->cbc_realm = cb;
00999 }
01000
01013 Gsasl_client_callback_realm
01014 gsasl_client_callback_realm_get (Gsasl * ctx)
01015 {
01016 return ctx ? ctx->cbc_realm : NULL;
01017 }
01018
01034 void
01035 gsasl_server_callback_validate_set (Gsasl * ctx,
01036 Gsasl_server_callback_validate cb)
01037 {
01038 ctx->cbs_validate = cb;
01039 }
01040
01053 Gsasl_server_callback_validate
01054 gsasl_server_callback_validate_get (Gsasl * ctx)
01055 {
01056 return ctx ? ctx->cbs_validate : NULL;
01057 }
01058
01074 void
01075 gsasl_server_callback_retrieve_set (Gsasl * ctx,
01076 Gsasl_server_callback_retrieve cb)
01077 {
01078 ctx->cbs_retrieve = cb;
01079 }
01080
01093 Gsasl_server_callback_retrieve
01094 gsasl_server_callback_retrieve_get (Gsasl * ctx)
01095 {
01096 return ctx ? ctx->cbs_retrieve : NULL;
01097 }
01098
01114 void
01115 gsasl_server_callback_cram_md5_set (Gsasl * ctx,
01116 Gsasl_server_callback_cram_md5 cb)
01117 {
01118 ctx->cbs_cram_md5 = cb;
01119 }
01120
01133 Gsasl_server_callback_cram_md5
01134 gsasl_server_callback_cram_md5_get (Gsasl * ctx)
01135 {
01136 return ctx ? ctx->cbs_cram_md5 : NULL;
01137 }
01138
01154 void
01155 gsasl_server_callback_digest_md5_set (Gsasl * ctx,
01156 Gsasl_server_callback_digest_md5 cb)
01157 {
01158 ctx->cbs_digest_md5 = cb;
01159 }
01160
01173 Gsasl_server_callback_digest_md5
01174 gsasl_server_callback_digest_md5_get (Gsasl * ctx)
01175 {
01176 return ctx->cbs_digest_md5;
01177 }
01178
01193 void
01194 gsasl_server_callback_external_set (Gsasl * ctx,
01195 Gsasl_server_callback_external cb)
01196 {
01197 ctx->cbs_external = cb;
01198 }
01199
01212 Gsasl_server_callback_external
01213 gsasl_server_callback_external_get (Gsasl * ctx)
01214 {
01215 return ctx ? ctx->cbs_external : NULL;
01216 }
01217
01232 void
01233 gsasl_server_callback_anonymous_set (Gsasl * ctx,
01234 Gsasl_server_callback_anonymous cb)
01235 {
01236 ctx->cbs_anonymous = cb;
01237 }
01238
01251 Gsasl_server_callback_anonymous
01252 gsasl_server_callback_anonymous_get (Gsasl * ctx)
01253 {
01254 return ctx ? ctx->cbs_anonymous : NULL;
01255 }
01256
01272 void
01273 gsasl_server_callback_realm_set (Gsasl * ctx, Gsasl_server_callback_realm cb)
01274 {
01275 ctx->cbs_realm = cb;
01276 }
01277
01290 Gsasl_server_callback_realm
01291 gsasl_server_callback_realm_get (Gsasl * ctx)
01292 {
01293 return ctx ? ctx->cbs_realm : NULL;
01294 }
01295
01312 void
01313 gsasl_server_callback_qop_set (Gsasl * ctx, Gsasl_server_callback_qop cb)
01314 {
01315 ctx->cbs_qop = cb;
01316 }
01317
01330 Gsasl_server_callback_qop
01331 gsasl_server_callback_qop_get (Gsasl * ctx)
01332 {
01333 return ctx ? ctx->cbs_qop : NULL;
01334 }
01335
01353 void
01354 gsasl_server_callback_maxbuf_set (Gsasl * ctx,
01355 Gsasl_server_callback_maxbuf cb)
01356 {
01357 ctx->cbs_maxbuf = cb;
01358 }
01359
01372 Gsasl_server_callback_maxbuf
01373 gsasl_server_callback_maxbuf_get (Gsasl * ctx)
01374 {
01375 return ctx ? ctx->cbs_maxbuf : NULL;
01376 }
01377
01394 void
01395 gsasl_server_callback_cipher_set (Gsasl * ctx,
01396 Gsasl_server_callback_cipher cb)
01397 {
01398 ctx->cbs_cipher = cb;
01399 }
01400
01413 Gsasl_server_callback_cipher
01414 gsasl_server_callback_cipher_get (Gsasl * ctx)
01415 {
01416 return ctx ? ctx->cbs_cipher : NULL;
01417 }
01418
01440 void
01441 gsasl_server_callback_securid_set (Gsasl * ctx,
01442 Gsasl_server_callback_securid cb)
01443 {
01444 ctx->cbs_securid = cb;
01445 }
01446
01459 Gsasl_server_callback_securid
01460 gsasl_server_callback_securid_get (Gsasl * ctx)
01461 {
01462 return ctx ? ctx->cbs_securid : NULL;
01463 }
01464
01482 void
01483 gsasl_server_callback_gssapi_set (Gsasl * ctx,
01484 Gsasl_server_callback_gssapi cb)
01485 {
01486 ctx->cbs_gssapi = cb;
01487 }
01488
01501 Gsasl_server_callback_gssapi
01502 gsasl_server_callback_gssapi_get (Gsasl * ctx)
01503 {
01504 return ctx ? ctx->cbs_gssapi : NULL;
01505 }
01506
01523 void
01524 gsasl_server_callback_service_set (Gsasl * ctx,
01525 Gsasl_server_callback_service cb)
01526 {
01527 ctx->cbs_service = cb;
01528 }
01529
01542 Gsasl_server_callback_service
01543 gsasl_server_callback_service_get (Gsasl * ctx)
01544 {
01545 return ctx ? ctx->cbs_service : NULL;
01546 }
01547
01548 #if WITH_SASLPREP
01549 # include <stringprep.h>
01550 #endif
01551
01578 char *
01579 gsasl_stringprep_nfkc (const char *in, ssize_t len)
01580 {
01581 char *out = NULL;
01582
01583 #if WITH_SASLPREP
01584 out = stringprep_utf8_nfkc_normalize (in, len);
01585 #endif
01586
01587 return out;
01588 }
01589
01609 char *
01610 gsasl_stringprep_saslprep (const char *in, int *stringprep_rc)
01611 {
01612 char *out = NULL;
01613 #if WITH_SASLPREP
01614 int rc;
01615
01616 rc = stringprep_profile (in, &out, "SASLprep", 0);
01617 if (stringprep_rc)
01618 *stringprep_rc = rc;
01619 if (rc != STRINGPREP_OK)
01620 out = NULL;
01621 #endif
01622
01623 return out;
01624 }
01625
01643 char *
01644 gsasl_stringprep_trace (const char *in, int *stringprep_rc)
01645 {
01646 char *out = NULL;
01647 #if WITH_SASLPREP
01648 int rc;
01649
01650 rc = stringprep_profile (in, &out, "trace", 0);
01651 if (stringprep_rc)
01652 *stringprep_rc = rc;
01653 if (rc != STRINGPREP_OK)
01654 out = NULL;
01655 #endif
01656
01657 return out;
01658 }
01659
01684 int
01685 gsasl_md5pwd_get_password (const char *filename,
01686 const char *username, char *key, size_t * keylen)
01687 {
01688 char matchbuf[BUFSIZ];
01689 char line[BUFSIZ];
01690 FILE *fh;
01691
01692 fh = fopen (filename, "r");
01693 if (fh == NULL)
01694 return GSASL_FOPEN_ERROR;
01695
01696 sprintf (matchbuf, "%s\t", username);
01697
01698 while (!feof (fh))
01699 {
01700 if (fgets (line, BUFSIZ, fh) == NULL)
01701 break;
01702
01703 if (line[0] == '#')
01704 continue;
01705
01706 while (strlen (line) > 0 && (line[strlen (line) - 1] == '\n' ||
01707 line[strlen (line) - 1] == '\r'))
01708 line[strlen (line) - 1] = '\0';
01709
01710 if (strlen (line) <= strlen (matchbuf))
01711 continue;
01712
01713 if (strncmp (matchbuf, line, strlen (matchbuf)) == 0)
01714 {
01715 if (*keylen < strlen (line) - strlen (matchbuf))
01716 {
01717 fclose (fh);
01718 return GSASL_TOO_SMALL_BUFFER;
01719 }
01720
01721 *keylen = strlen (line) - strlen (matchbuf);
01722
01723 if (key)
01724 memcpy (key, &line[strlen (matchbuf)], *keylen);
01725
01726 fclose (fh);
01727
01728 return GSASL_OK;
01729 }
01730 }
01731
01732 if (fclose (fh) != 0)
01733 return GSASL_FCLOSE_ERROR;
01734
01735 return GSASL_AUTHENTICATION_ERROR;
01736 }
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781 #include <ctype.h>
01782 #include <stdio.h>
01783
01784 #define Assert(Cond) if (!(Cond)) abort()
01785
01786 static const char Base64[] =
01787 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
01788 static const char Pad64 = '=';
01789
01806 int
01807 gsasl_base64_encode (char const *src,
01808 size_t srclength, char *target, size_t targsize)
01809 {
01810 size_t datalength = 0;
01811 unsigned char input[3];
01812 unsigned char output[4];
01813 size_t i;
01814
01815 while (2 < srclength)
01816 {
01817 input[0] = *src++;
01818 input[1] = *src++;
01819 input[2] = *src++;
01820 srclength -= 3;
01821
01822 output[0] = input[0] >> 2;
01823 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
01824 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
01825 output[3] = input[2] & 0x3f;
01826 Assert (output[0] < 64);
01827 Assert (output[1] < 64);
01828 Assert (output[2] < 64);
01829 Assert (output[3] < 64);
01830
01831 if (datalength + 4 > targsize)
01832 return (-1);
01833 target[datalength++] = Base64[output[0]];
01834 target[datalength++] = Base64[output[1]];
01835 target[datalength++] = Base64[output[2]];
01836 target[datalength++] = Base64[output[3]];
01837 }
01838
01839
01840 if (0 != srclength)
01841 {
01842
01843 input[0] = input[1] = input[2] = '\0';
01844 for (i = 0; i < srclength; i++)
01845 input[i] = *src++;
01846
01847 output[0] = input[0] >> 2;
01848 output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
01849 output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
01850 Assert (output[0] < 64);
01851 Assert (output[1] < 64);
01852 Assert (output[2] < 64);
01853
01854 if (datalength + 4 > targsize)
01855 return (-1);
01856 target[datalength++] = Base64[output[0]];
01857 target[datalength++] = Base64[output[1]];
01858 if (srclength == 1)
01859 target[datalength++] = Pad64;
01860 else
01861 target[datalength++] = Base64[output[2]];
01862 target[datalength++] = Pad64;
01863 }
01864 if (datalength >= targsize)
01865 return (-1);
01866 target[datalength] = '\0';
01867 return (datalength);
01868 }
01869
01885 int
01886 gsasl_base64_decode (char const *src, char *target, size_t targsize)
01887 {
01888 int tarindex, state, ch;
01889 char *pos;
01890
01891 state = 0;
01892 tarindex = 0;
01893
01894 while ((ch = *src++) != '\0')
01895 {
01896 if (isspace (ch))
01897 continue;
01898
01899 if (ch == Pad64)
01900 break;
01901
01902 pos = strchr (Base64, ch);
01903 if (pos == 0)
01904 return (-1);
01905
01906 switch (state)
01907 {
01908 case 0:
01909 if (target)
01910 {
01911 if ((size_t) tarindex >= targsize)
01912 return (-1);
01913 target[tarindex] = (pos - Base64) << 2;
01914 }
01915 state = 1;
01916 break;
01917 case 1:
01918 if (target)
01919 {
01920 if ((size_t) tarindex + 1 >= targsize)
01921 return (-1);
01922 target[tarindex] |= (pos - Base64) >> 4;
01923 target[tarindex + 1] = ((pos - Base64) & 0x0f) << 4;
01924 }
01925 tarindex++;
01926 state = 2;
01927 break;
01928 case 2:
01929 if (target)
01930 {
01931 if ((size_t) tarindex + 1 >= targsize)
01932 return (-1);
01933 target[tarindex] |= (pos - Base64) >> 2;
01934 target[tarindex + 1] = ((pos - Base64) & 0x03) << 6;
01935 }
01936 tarindex++;
01937 state = 3;
01938 break;
01939 case 3:
01940 if (target)
01941 {
01942 if ((size_t) tarindex >= targsize)
01943 return (-1);
01944 target[tarindex] |= (pos - Base64);
01945 }
01946 tarindex++;
01947 state = 0;
01948 break;
01949 default:
01950 abort ();
01951 }
01952 }
01953
01954
01955
01956
01957
01958
01959 if (ch == Pad64)
01960 {
01961 ch = *src++;
01962 switch (state)
01963 {
01964 case 0:
01965 case 1:
01966 return (-1);
01967
01968 case 2:
01969
01970 for ((void) NULL; ch != '\0'; ch = *src++)
01971 if (!isspace (ch))
01972 break;
01973
01974 if (ch != Pad64)
01975 return (-1);
01976 ch = *src++;
01977
01978
01979
01980 case 3:
01981
01982
01983
01984
01985 for ((void) NULL; ch != '\0'; ch = *src++)
01986 if (!isspace (ch))
01987 return (-1);
01988
01989
01990
01991
01992
01993
01994
01995 if (target && target[tarindex] != 0)
01996 return (-1);
01997 }
01998 }
01999 else
02000 {
02001
02002
02003
02004
02005 if (state != 0)
02006 return (-1);
02007 }
02008
02009 return (tarindex);
02010 }