/* -------------------------------- * init_query_cache_info() - allocate memory for query_cache_info and stores query * * returns 0 on success, -1 otherwise `* -------------------------------- */ static int init_query_cache_info(POOL_CONNECTION *pc, char *database, char *query) { int query_len; /* length of the SELECT query to be cached */ query_cache_info = (QueryCacheInfo *)malloc(sizeof(QueryCacheInfo)); if (malloc_failed(query_cache_info)) return -1; /* query */ query_len = strlen(query); query_cache_info->query = (char *)malloc(query_len + 1); if (malloc_failed(query_cache_info->query)) return -1; memcpy(query_cache_info->query, query, query_len + 1); /* md5_query */ query_cache_info->md5_query = (char *)malloc(33); /* md5sum is always 33 bytes (including the '\0') */ if (malloc_failed(query_cache_info->md5_query)) return -1; pool_md5_hash(query_cache_info->query, query_len, query_cache_info->md5_query); /* malloc DEFAULT_CACHE_SIZE for query_cache_info->cache */ query_cache_info->cache = (char *)malloc(DEFAULT_CACHE_SIZE); if (malloc_failed(query_cache_info->cache)) return -1; query_cache_info->cache_size = DEFAULT_CACHE_SIZE; query_cache_info->cache_offset = 0; /* save database name */ query_cache_info->db_name = (char *)malloc(strlen(database)+1); if (malloc_failed(query_cache_info->db_name)) return -1; strcpy(query_cache_info->db_name, database); /* initialize create_timestamp */ query_cache_info->create_time = NULL; return 0; }
/* * Computes MD5 checksum of "passwd" (a null-terminated string) followed * by "salt" (which need not be null-terminated). * * Output format is a 32-hex-digit MD5 checksum. * Hence, the output buffer "buf" must be at least 33 bytes long. * * Returns 1 if okay, 0 on error (out of memory). */ int pool_md5_encrypt(const char *passwd, const char *salt, size_t salt_len, char *buf) { size_t passwd_len = strlen(passwd); char *crypt_buf = malloc(passwd_len + salt_len); int ret; if (!crypt_buf) return 0; /* failed */ /* * Place salt at the end because it may be known by users trying to crack * the MD5 output. */ strcpy(crypt_buf, passwd); memcpy(crypt_buf + passwd_len, salt, salt_len); ret = pool_md5_hash(crypt_buf, passwd_len + salt_len, buf); free(crypt_buf); return ret; }
/* -------------------------------- * pcp_authorize - authenticate with pgpool using username and password * * return 0 on success, -1 otherwise * -------------------------------- */ static int pcp_authorize(char *username, char *password) { char tos; char *buf = NULL; int wsize; int rsize; char salt[4]; char encrypt_buf[(MD5_PASSWD_LEN+1)*2]; char md5[MD5_PASSWD_LEN+1]; /* request salt */ pcp_write(pc, "M", 1); wsize = htonl(sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return -1; } if (pcp_read(pc, &tos, 1)) return -1; if (pcp_read(pc, &rsize, sizeof(int))) return -1; rsize = ntohl(rsize); buf = (char *)malloc(rsize); if (buf == NULL) { errorcode = NOMEMERR; return -1; } if (pcp_read(pc, buf, rsize - sizeof(int))) return -1; memcpy(salt, buf, 4); free(buf); /* encrypt password */ pool_md5_hash(password, strlen(password), md5); md5[MD5_PASSWD_LEN] = '\0'; pool_md5_encrypt(md5, username, strlen(username), encrypt_buf + MD5_PASSWD_LEN + 1); encrypt_buf[(MD5_PASSWD_LEN+1)*2-1] = '\0'; pool_md5_encrypt(encrypt_buf+MD5_PASSWD_LEN+1, salt, 4, encrypt_buf); encrypt_buf[MD5_PASSWD_LEN] = '\0'; pcp_write(pc, "R", 1); wsize = htonl((strlen(username)+1 + strlen(encrypt_buf)+1) + sizeof(int)); pcp_write(pc, &wsize, sizeof(int)); pcp_write(pc, username, strlen(username)+1); pcp_write(pc, encrypt_buf, strlen(encrypt_buf)+1); if (pcp_flush(pc) < 0) { if (debug) fprintf(stderr, "DEBUG: could not send data to backend\n"); return -1; } if (debug) fprintf(stderr, "DEBUG: send: tos=\"R\", len=%d\n", ntohl(wsize)); if (pcp_read(pc, &tos, 1)) return -1; if (pcp_read(pc, &rsize, sizeof(int))) return -1; rsize = ntohl(rsize); buf = (char *)malloc(rsize); if (buf == NULL) { errorcode = NOMEMERR; return -1; } if (pcp_read(pc, buf, rsize - sizeof(int))) return -1; if (debug) fprintf(stderr, "DEBUG: recv: tos=\"%c\", len=%d, data=%s\n", tos, rsize, buf); if (tos == 'e') { if (debug) fprintf(stderr, "DEBUG: command failed. reason=%s\n", buf); errorcode = BACKENDERR; } else if (tos == 'r') { if (strcmp(buf, "AuthenticationOK") == 0) { free(buf); return 0; } if (debug) fprintf(stderr, "DEBUG: authentication failed. reason=%s\n", buf); errorcode = AUTHERR; } free(buf); return -1; }
/* -------------------------------- * pcp_authorize - authenticate with pgpool using username and password * * return 0 on success, -1 otherwise * -------------------------------- */ static int pcp_authorize(PCPConnInfo* pcpConn, char *username, char *password) { int wsize; char salt[4]; char* salt_ptr; char encrypt_buf[(MD5_PASSWD_LEN+1)*2]; char md5[MD5_PASSWD_LEN+1]; PCPResultInfo* pcpRes; if (password == NULL) password = ""; if (username == NULL) username = ""; if (PCPConnectionStatus(pcpConn) != PCP_CONNECTION_CONNECTED) { pcp_internal_error(pcpConn, "ERROR: PCP authorization failed. invalid connection state."); return -1; } if (strlen(username) >= MAX_USER_PASSWD_LEN) { pcp_internal_error(pcpConn, "ERROR: PCP authorization failed. username too long."); return -1; } /* request salt */ pcp_write(pcpConn->pcpConn, "M", 1); wsize = htonl(sizeof(int)); pcp_write(pcpConn->pcpConn, &wsize, sizeof(int)); if (PCPFlush(pcpConn) < 0) return -1; pcpRes = process_pcp_response(pcpConn, 'M'); if(PCPResultStatus(pcpRes) != PCP_RES_COMMAND_OK) return -1; salt_ptr = pcp_get_binary_data(pcpRes, 0); if(salt_ptr == NULL) return -1; memcpy(salt, salt_ptr, 4); /* encrypt password */ pool_md5_hash(password, strlen(password), md5); md5[MD5_PASSWD_LEN] = '\0'; pool_md5_encrypt(md5, username, strlen(username), encrypt_buf + MD5_PASSWD_LEN + 1); encrypt_buf[(MD5_PASSWD_LEN+1)*2-1] = '\0'; pool_md5_encrypt(encrypt_buf+MD5_PASSWD_LEN+1, salt, 4, encrypt_buf); encrypt_buf[MD5_PASSWD_LEN] = '\0'; pcp_write(pcpConn->pcpConn, "R", 1); wsize = htonl((strlen(username)+1 + strlen(encrypt_buf)+1) + sizeof(int)); pcp_write(pcpConn->pcpConn, &wsize, sizeof(int)); pcp_write(pcpConn->pcpConn, username, strlen(username)+1); pcp_write(pcpConn->pcpConn, encrypt_buf, strlen(encrypt_buf)+1); if (PCPFlush(pcpConn) < 0) return -1; pcpRes = process_pcp_response(pcpConn, 'R'); if(PCPResultStatus(pcpRes) != PCP_RES_COMMAND_OK) return -1; pcp_free_result(pcpConn); return 0; }
/* -------------------------------- * pool_query_cache_lookup - retrieve query cache from the SystemDB * * creates a SQL query string for searching a cache from the SystemDB. * * returns POOL_CONTINUE if cache is found. returns POOL_END if cache was * not found. returns POOL_ERROR if an error has been encountered while * searching. * * Note that POOL_END and POOL_ERROR are treated the same by the caller * (pool_process_query.c). * POOL_END and POOL_ERROR both indicates to the caller that the search * query must be forwarded to the backends in order to retrieve data and * the result be cached. * Only difference is that POOL_ERROR indicates that some fatal error has * occured; query cache function, however, should be seemless to the user * whether cache was not found or error has occured during cache retrieve. * -------------------------------- */ POOL_STATUS pool_query_cache_lookup(POOL_CONNECTION *frontend, char *query, char *database, char tstate) { char *sql = NULL; int sql_len; char md5_query[33]; struct timeval timeout; int status; if (! system_db_connection_exists()) return POOL_ERROR; /* same as POOL_END ... at least for now */ sql_len = strlen(pool_config->system_db_schema) + strlen(QUERY_CACHE_TABLE_NAME) + sizeof(md5_query) + strlen(database) + 64; sql = (char *)malloc(sql_len); if (malloc_failed(sql)) return POOL_ERROR; /* should I exit here rather than returning an error? */ /* cached data lookup */ pool_md5_hash(query, strlen(query), md5_query); snprintf(sql, sql_len, "SELECT value FROM %s.%s WHERE hash = '%s' AND dbname = '%s'", pool_config->system_db_schema, QUERY_CACHE_TABLE_NAME, md5_query, database); /* set timeout value for select */ timeout.tv_sec = pool_config->child_life_time; timeout.tv_usec = 0; pool_debug("pool_query_cache_lookup: searching cache for query: \"%s\"", query); status = search_system_db_for_cache(frontend, sql, strlen(sql)+1, &timeout, tstate); /* make sure that the remaining data is discarded */ SYSDB_CON->po = 0; SYSDB_CON->len = 0; free(sql); /* cache found, and no backend communication needed */ if (status == CACHE_FOUND) { return POOL_CONTINUE; } /* cache not found */ if (status == CACHE_ERROR) { pool_error("pool_query_cache_lookup: query cache lookup failed"); /* reset the SystemDB connection */ if (system_db_info->pgconn) pool_close_libpq_connection(); return POOL_ERROR; /* same as POOL_END ... at least for now */ } pool_debug("pool_query_cache_lookup: query cache not found"); return POOL_END; }
int main(int argc, char *argv[]) { #define PRINT_USAGE(exit_code) print_usage(argv[0], exit_code) char conf_file[POOLMAXPATHLEN+1]; char username[MAX_INPUT_SIZE+1]; int opt; int optindex; bool md5auth = false; bool prompt = false; static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"prompt", no_argument, NULL, 'p'}, {"md5auth", no_argument, NULL, 'm'}, {"username", required_argument, NULL, 'u'}, {"config-file", required_argument, NULL, 'f'}, {NULL, 0, NULL, 0} }; snprintf(conf_file, sizeof(conf_file), "%s/%s", DEFAULT_CONFIGDIR, POOL_CONF_FILE_NAME); /* initialize username buffer with zeros so that we can use strlen on it later to check if a username was given on the command line */ memset(username, 0, MAX_INPUT_SIZE+1); while ((opt = getopt_long(argc, argv, "hpmf:u:", long_options, &optindex)) != -1) { switch (opt) { case 'p': /* prompt for password */ prompt = true; break; case 'm': /* produce md5 authentication password */ md5auth = true; break; case 'f': /* specify configuration file */ if (!optarg) { PRINT_USAGE(EXIT_SUCCESS); } strlcpy(conf_file, optarg, sizeof(conf_file)); break; case 'u': if (!optarg) { PRINT_USAGE(EXIT_SUCCESS); } /* check the input limit early */ if (strlen(optarg) > MAX_INPUT_SIZE) { fprintf(stderr, "Error: input exceeds maximum username length!\n\n"); exit(EXIT_FAILURE); } strlcpy(username, optarg, sizeof(username)); break; default: PRINT_USAGE(EXIT_SUCCESS); break; } } /* Prompt for password. */ if (prompt) { char md5[MD5_PASSWD_LEN+1]; char buf[MAX_INPUT_SIZE+1]; int len; set_tio_attr(1); printf("password: "******"Couldn't read input from stdin. (fgets(): %s)", strerror(eno)); exit(EXIT_FAILURE); } printf("\n"); set_tio_attr(0); /* Remove LF at the end of line, if there is any. */ len = strlen(buf); if (len > 0 && buf[len-1] == '\n') { buf[len-1] = '\0'; len--; } if (md5auth) { update_pool_passwd(conf_file, username, buf); } else { pool_md5_hash(buf, len, md5); printf("%s\n", md5); } } /* Read password from argv. */ else { char md5[POOL_PASSWD_LEN+1]; int len; if (optind >= argc) { PRINT_USAGE(EXIT_FAILURE); } len = strlen(argv[optind]); if (len > MAX_INPUT_SIZE) { fprintf(stderr, "Error: Input exceeds maximum password length!\n\n"); PRINT_USAGE(EXIT_FAILURE); } if (md5auth) { update_pool_passwd(conf_file, username, argv[optind]); } else { pool_md5_hash(argv[optind], len, md5); printf("%s\n", md5); } } return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { #define PRINT_USAGE(exit_code) print_usage(argv[0], exit_code) #define COMPARE_ARG(arg) (!strcmp(argv[1], arg)) if (argc != 2) PRINT_USAGE(EXIT_FAILURE); else if (COMPARE_ARG("--help") || COMPARE_ARG("-h")) PRINT_USAGE(EXIT_SUCCESS); /* Prompt for password. */ else if (COMPARE_ARG("--prompt") || COMPARE_ARG("-p")) { char md5[MD5_PASSWD_LEN+1]; char buf[MAX_INPUT_SIZE+1]; int len; set_tio_attr(1); printf("password: "******"Couldn't read input from stdin. (fgets(): %s)", strerror(eno)); exit(EXIT_FAILURE); } set_tio_attr(0); /* Remove LF at the end of line, if there is any. */ len = strlen(buf); if (len > 0 && buf[len-1] == '\n') { buf[len-1] = '\0'; len--; } pool_md5_hash(buf, len, md5); printf("\n%s\n", md5); } /* Read password from argv[1]. */ else { char md5[MD5_PASSWD_LEN+1]; int len = strlen(argv[1]); if (len > MAX_INPUT_SIZE) { fprintf(stderr, "Error: Input exceeds maximum password length!\n\n"); PRINT_USAGE(EXIT_FAILURE); } pool_md5_hash(argv[1], len, md5); printf("%s\n", md5); } return EXIT_SUCCESS; }