Server IP : 172.67.216.182 / Your IP : 162.158.88.135 Web Server : Apache System : Linux krdc-ubuntu-s-2vcpu-4gb-amd-blr1-01.localdomain 5.15.0-142-generic #152-Ubuntu SMP Mon May 19 10:54:31 UTC 2025 x86_64 User : www ( 1000) PHP Version : 7.4.33 Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /www/server/mysql/src/mysys_ssl/ |
Upload File : |
/* Copyright (c) 2011, 2023, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the Free Software Foundation. This program is also distributed with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in included license documentation. The authors of MySQL hereby grant you an additional permission to link the program and your derivative works with the separately licensed software that they have included with MySQL. Without limiting anything contained in the foregoing, this file, which is part of C Driver for MySQL (Connector/C), is also subject to the Universal FOSS Exception, version 1.0, a copy of which can be found at http://oss.oracle.com/licenses/universal-foss-exception. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ // First include (the generated) my_config.h, to get correct platform defines. #include "my_config.h" #ifdef HAVE_OPENSSL #include <openssl/sha.h> #include <openssl/rand.h> #include "crypt_genhash_impl.h" #include "m_string.h" #include <stdint.h> #include <time.h> #include <string.h> #ifdef HAVE_ALLOCA_H #include <alloca.h> #endif #define DIGEST_CTX SHA256_CTX #define DIGESTInit SHA256_Init #define DIGESTUpdate SHA256_Update #define DIGESTFinal SHA256_Final #define DIGEST_LEN SHA256_DIGEST_LENGTH static const char crypt_alg_magic[] = "$5"; #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif /** Size-bounded string copying and concatenation This is a replacement for STRLCPY(3) */ size_t strlcat(char *dst, const char *src, size_t siz) { char *d= dst; const char *s= src; size_t n= siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen= d - dst; n= siz - dlen; if (n == 0) return(dlen + siz); while (*s != '\0') { if (n != 1) { *d++= *s; n--; } s++; } *d= '\0'; return(dlen + (s - src)); /* count does not include NUL */ } static const int crypt_alg_magic_len = sizeof (crypt_alg_magic) - 1; static unsigned char b64t[] = /* 0 ... 63 => ascii - 64 */ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; #define b64_from_24bit(B2, B1, B0, N) \ { \ uint32_t w = ((B2) << 16) | ((B1) << 8) | (B0); \ int n = (N); \ while (--n >= 0 && ctbufflen > 0) { \ *p++ = b64t[w & 0x3f]; \ w >>= 6; \ ctbufflen--; \ } \ } #define ROUNDS "rounds=" #define ROUNDSLEN (sizeof (ROUNDS) - 1) /** Get the integer value after rounds= where ever it occurs in the string. if the last char after the int is a , or $ that is fine anything else is an error. */ static uint getrounds(const char *s) { const char *r; const char *p; char *e; long val; if (s == NULL) return (0); if ((r = strstr(s, ROUNDS)) == NULL) { return (0); } if (strncmp(r, ROUNDS, ROUNDSLEN) != 0) { return (0); } p= r + ROUNDSLEN; errno= 0; val= strtol(p, &e, 10); /* An error occurred or there is non-numeric stuff at the end which isn't one of the crypt(3c) special chars ',' or '$' */ if (errno != 0 || val < 0 || !(*e == '\0' || *e == ',' || *e == '$')) { return (0); } return ((uint32_t) val); } /** Finds the interval which envelopes the user salt in a crypt password The crypt format is assumed to be $a$bbbb$cccccc\0 and the salt is found by counting the delimiters and marking begin and end. @param salt_being[in] Pointer to start of crypt passwd @param salt_being[out] Pointer to first byte of the salt @param salt_end[in] Pointer to the last byte in passwd @param salt_end[out] Pointer to the byte immediatly following the salt ($) @return The size of the salt identified */ int extract_user_salt(char **salt_begin, char **salt_end) { char *it= *salt_begin; int delimiter_count= 0; while(it != *salt_end) { if (*it == '$') { ++delimiter_count; if (delimiter_count == 2) { *salt_begin= it + 1; } if (delimiter_count == 3) break; } ++it; } *salt_end= it; return *salt_end - *salt_begin; } const char *sha256_find_digest(char *pass) { int sz= strlen(pass); return pass + sz - SHA256_HASH_LENGTH; } /* * Portions of the below code come from crypt_bsdmd5.so (bsdmd5.c) : * ---------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * <[email protected]> wrote this file. As long as you retain this notice you * can do whatever you want with this stuff. If we meet some day, and you think * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp * ---------------------------------------------------------------------------- * * $FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp $ * */ /* * The below code implements the specification from: * * From http://people.redhat.com/drepper/SHA-crypt.txt * * Portions of the code taken from inspired by or verified against the * source in the above document which is licensed as: * * "Released into the Public Domain by Ulrich Drepper <[email protected]>." */ /* Due to a Solaris namespace bug DS is a reserved word. To work around this DS is undefined. */ #undef DS /* ARGSUSED4 */ extern "C" char * my_crypt_genhash(char *ctbuffer, size_t ctbufflen, const char *plaintext, size_t plaintext_len, const char *switchsalt, const char **params) { int salt_len; size_t i; char *salt; unsigned char A[DIGEST_LEN]; unsigned char B[DIGEST_LEN]; unsigned char DP[DIGEST_LEN]; unsigned char DS[DIGEST_LEN]; DIGEST_CTX ctxA, ctxB, ctxC, ctxDP, ctxDS; uint rounds = ROUNDS_DEFAULT; int srounds = 0; bool custom_rounds= false; char *p; char *P, *Pp; char *S, *Sp; /* Refine the salt */ salt = (char *)switchsalt; /* skip our magic string */ if (strncmp(salt, crypt_alg_magic, crypt_alg_magic_len) == 0) { salt += crypt_alg_magic_len + 1; } srounds = getrounds(salt); if (srounds != 0) { rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX)); custom_rounds= true; p = strchr(salt, '$'); if (p != NULL) salt = p + 1; } salt_len = MIN(strcspn(salt, "$"), CRYPT_SALT_LENGTH); //plaintext_len = strlen(plaintext); /* 1. */ DIGESTInit(&ctxA); /* 2. The password first, since that is what is most unknown */ DIGESTUpdate(&ctxA, plaintext, plaintext_len); /* 3. Then the raw salt */ DIGESTUpdate(&ctxA, salt, salt_len); /* 4. - 8. */ DIGESTInit(&ctxB); DIGESTUpdate(&ctxB, plaintext, plaintext_len); DIGESTUpdate(&ctxB, salt, salt_len); DIGESTUpdate(&ctxB, plaintext, plaintext_len); DIGESTFinal(B, &ctxB); /* 9. - 10. */ for (i= plaintext_len; i > MIXCHARS; i -= MIXCHARS) DIGESTUpdate(&ctxA, B, MIXCHARS); DIGESTUpdate(&ctxA, B, i); /* 11. */ for (i= plaintext_len; i > 0; i >>= 1) { if ((i & 1) != 0) { DIGESTUpdate(&ctxA, B, MIXCHARS); } else { DIGESTUpdate(&ctxA, plaintext, plaintext_len); } } /* 12. */ DIGESTFinal(A, &ctxA); /* 13. - 15. */ DIGESTInit(&ctxDP); for (i= 0; i < plaintext_len; i++) DIGESTUpdate(&ctxDP, plaintext, plaintext_len); DIGESTFinal(DP, &ctxDP); /* 16. */ Pp= P= (char *)alloca(plaintext_len); for (i= plaintext_len; i >= MIXCHARS; i -= MIXCHARS) { Pp= (char *)(memcpy(Pp, DP, MIXCHARS)) + MIXCHARS; } (void) memcpy(Pp, DP, i); /* 17. - 19. */ DIGESTInit(&ctxDS); for (i= 0; i < 16U + (uint8_t)A[0]; i++) DIGESTUpdate(&ctxDS, salt, salt_len); DIGESTFinal(DS, &ctxDS); /* 20. */ Sp= S= (char *)alloca(salt_len); for (i= salt_len; i >= MIXCHARS; i -= MIXCHARS) { Sp= (char *)(memcpy(Sp, DS, MIXCHARS)) + MIXCHARS; } (void) memcpy(Sp, DS, i); /* 21. */ for (i= 0; i < rounds; i++) { DIGESTInit(&ctxC); if ((i & 1) != 0) { DIGESTUpdate(&ctxC, P, plaintext_len); } else { if (i == 0) DIGESTUpdate(&ctxC, A, MIXCHARS); else DIGESTUpdate(&ctxC, DP, MIXCHARS); } if (i % 3 != 0) { DIGESTUpdate(&ctxC, S, salt_len); } if (i % 7 != 0) { DIGESTUpdate(&ctxC, P, plaintext_len); } if ((i & 1) != 0) { if (i == 0) DIGESTUpdate(&ctxC, A, MIXCHARS); else DIGESTUpdate(&ctxC, DP, MIXCHARS); } else { DIGESTUpdate(&ctxC, P, plaintext_len); } DIGESTFinal(DP, &ctxC); } /* 22. Now make the output string */ if (custom_rounds) { (void) my_snprintf(ctbuffer, ctbufflen, "%s$rounds=%zu$", crypt_alg_magic, (size_t)rounds); } else { (void) my_snprintf(ctbuffer, ctbufflen, "%s$", crypt_alg_magic); } (void) strncat(ctbuffer, (const char *)salt, salt_len); (void) strlcat(ctbuffer, "$", ctbufflen); p= ctbuffer + strlen(ctbuffer); ctbufflen -= strlen(ctbuffer); b64_from_24bit(DP[ 0], DP[10], DP[20], 4); b64_from_24bit(DP[21], DP[ 1], DP[11], 4); b64_from_24bit(DP[12], DP[22], DP[ 2], 4); b64_from_24bit(DP[ 3], DP[13], DP[23], 4); b64_from_24bit(DP[24], DP[ 4], DP[14], 4); b64_from_24bit(DP[15], DP[25], DP[ 5], 4); b64_from_24bit(DP[ 6], DP[16], DP[26], 4); b64_from_24bit(DP[27], DP[ 7], DP[17], 4); b64_from_24bit(DP[18], DP[28], DP[ 8], 4); b64_from_24bit(DP[ 9], DP[19], DP[29], 4); b64_from_24bit(0, DP[31], DP[30], 3); *p= '\0'; (void) memset(A, 0, sizeof (A)); (void) memset(B, 0, sizeof (B)); (void) memset(DP, 0, sizeof (DP)); (void) memset(DS, 0, sizeof (DS)); return (ctbuffer); } /** Generate a random string using ASCII characters but avoid seperator character. Stdlib rand and srand are used to produce pseudo random numbers between with about 7 bit worth of entropty between 1-127. */ extern "C" void generate_user_salt(char *buffer, int buffer_len) { char *end= buffer + buffer_len - 1; RAND_bytes((unsigned char *) buffer, buffer_len); /* Sequence must be a legal UTF8 string */ for (; buffer < end; buffer++) { *buffer &= 0x7f; if (*buffer == '\0' || *buffer == '$') *buffer= *buffer + 1; } /* Make sure the buffer is terminated properly */ *end= '\0'; } void xor_string(char *to, int to_len, char *pattern, int pattern_len) { int loop= 0; while(loop <= to_len) { *(to + loop) ^= *(pattern + loop % pattern_len); ++loop; } } #endif // HAVE_OPENSSL