/* {{{ php_mail */ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char *extra_cmd) { #if (defined PHP_WIN32 || defined NETWARE) int tsm_err; char *tsm_errmsg = NULL; #endif FILE *sendmail; int ret; char *sendmail_path = INI_STR("sendmail_path"); char *sendmail_cmd = NULL; char *mail_log = INI_STR("mail.log"); char *hdr = headers; #if PHP_SIGCHILD void (*sig_handler)() = NULL; #endif #define MAIL_RET(val) \ if (hdr != headers) { \ efree(hdr); \ } \ return val; \ if (mail_log && *mail_log) { char *tmp; time_t curtime; size_t l; zend_string *date_str; time(&curtime); date_str = php_format_date("d-M-Y H:i:s e", 13, curtime, 1); l = spprintf(&tmp, 0, "[%s] mail() on [%s:%d]: To: %s -- Headers: %s\n", date_str->val, zend_get_executed_filename(), zend_get_executed_lineno(), to, hdr ? hdr : ""); zend_string_free(date_str); if (hdr) { php_mail_log_crlf_to_spaces(tmp); } if (!strcmp(mail_log, "syslog")) { /* Drop the final space when logging to syslog. */ tmp[l - 1] = 0; php_mail_log_to_syslog(tmp); } else { /* Convert the final space to a newline when logging to file. */ tmp[l - 1] = '\n'; php_mail_log_to_file(mail_log, tmp, l); } efree(tmp); } if (PG(mail_x_header)) { const char *tmp = zend_get_executed_filename(); zend_string *f; f = php_basename(tmp, strlen(tmp), NULL, 0); if (headers != NULL) { spprintf(&hdr, 0, "X-PHP-Originating-Script: " ZEND_LONG_FMT ":%s\n%s", php_getuid(), f->val, headers); } else { spprintf(&hdr, 0, "X-PHP-Originating-Script: " ZEND_LONG_FMT ":%s", php_getuid(), f->val); } zend_string_release(f); } if (!sendmail_path) { #if (defined PHP_WIN32 || defined NETWARE) /* handle old style win smtp sending */ if (TSendMail(INI_STR("SMTP"), &tsm_err, &tsm_errmsg, hdr, subject, to, message, NULL, NULL, NULL) == FAILURE) { if (tsm_errmsg) { php_error_docref(NULL, E_WARNING, "%s", tsm_errmsg); efree(tsm_errmsg); } else { php_error_docref(NULL, E_WARNING, "%s", GetSMErrorText(tsm_err)); } MAIL_RET(0); } MAIL_RET(1); #else MAIL_RET(0); #endif } if (extra_cmd != NULL) { spprintf(&sendmail_cmd, 0, "%s %s", sendmail_path, extra_cmd); } else { sendmail_cmd = sendmail_path; } #if PHP_SIGCHILD /* Set signal handler of SIGCHLD to default to prevent other signal handlers * from being called and reaping the return code when our child exits. * The original handler needs to be restored after pclose() */ sig_handler = (void *)signal(SIGCHLD, SIG_DFL); if (sig_handler == SIG_ERR) { sig_handler = NULL; } #endif #ifdef PHP_WIN32 sendmail = popen_ex(sendmail_cmd, "wb", NULL, NULL); #else /* Since popen() doesn't indicate if the internal fork() doesn't work * (e.g. the shell can't be executed) we explicitly set it to 0 to be * sure we don't catch any older errno value. */ errno = 0; sendmail = popen(sendmail_cmd, "w"); #endif if (extra_cmd != NULL) { efree (sendmail_cmd); } if (sendmail) { #ifndef PHP_WIN32 if (EACCES == errno) { php_error_docref(NULL, E_WARNING, "Permission denied: unable to execute shell to run mail delivery binary '%s'", sendmail_path); pclose(sendmail); #if PHP_SIGCHILD /* Restore handler in case of error on Windows Not sure if this applicable on Win but just in case. */ if (sig_handler) { signal(SIGCHLD, sig_handler); } #endif MAIL_RET(0); } #endif fprintf(sendmail, "To: %s\n", to); fprintf(sendmail, "Subject: %s\n", subject); if (hdr != NULL) { fprintf(sendmail, "%s\n", hdr); } fprintf(sendmail, "\n%s\n", message); ret = pclose(sendmail); #if PHP_SIGCHILD if (sig_handler) { signal(SIGCHLD, sig_handler); } #endif #ifdef PHP_WIN32 if (ret == -1) #else #if defined(EX_TEMPFAIL) if ((ret != EX_OK)&&(ret != EX_TEMPFAIL)) #elif defined(EX_OK) if (ret != EX_OK) #else if (ret != 0) #endif #endif { MAIL_RET(0); } else { MAIL_RET(1); } } else { php_error_docref(NULL, E_WARNING, "Could not execute mail delivery program '%s'", sendmail_path); #if PHP_SIGCHILD if (sig_handler) { signal(SIGCHLD, sig_handler); } #endif MAIL_RET(0); } MAIL_RET(1); /* never reached */ }
PHPAPI int php_checkuid_ex(const char *filename, const char *fopen_mode, int mode, int flags) { struct stat sb; int ret, nofile=0; long uid=0L, gid=0L, duid=0L, dgid=0L; char path[MAXPATHLEN]; char *s, filenamecopy[MAXPATHLEN]; TSRMLS_FETCH(); path[0] = '\0'; if (!filename) { return 0; /* path must be provided */ } if (strlcpy(filenamecopy, filename, MAXPATHLEN)>=MAXPATHLEN) { return 0; } filename=(char *)&filenamecopy; if (fopen_mode) { if (fopen_mode[0] == 'r') { mode = CHECKUID_DISALLOW_FILE_NOT_EXISTS; } else { mode = CHECKUID_CHECK_FILE_AND_DIR; } } /* First we see if the file is owned by the same user... * If that fails, passthrough and check directory... */ if (mode != CHECKUID_ALLOW_ONLY_DIR) { #if HAVE_BROKEN_GETCWD char ftest[MAXPATHLEN]; strcpy(ftest, filename); if (VCWD_GETCWD(ftest, sizeof(ftest)) == NULL) { strcpy(path, filename); } else #endif expand_filepath(filename, path TSRMLS_CC); ret = VCWD_STAT(path, &sb); if (ret < 0) { if (mode == CHECKUID_DISALLOW_FILE_NOT_EXISTS) { if ((flags & CHECKUID_NO_ERRORS) == 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to access %s", filename); } return 0; } else if (mode == CHECKUID_ALLOW_FILE_NOT_EXISTS) { if ((flags & CHECKUID_NO_ERRORS) == 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to access %s", filename); } return 1; } nofile = 1; } else { uid = sb.st_uid; gid = sb.st_gid; if (uid == php_getuid()) { return 1; } else if (PG(safe_mode_gid) && gid == php_getgid()) { return 1; } } /* Trim off filename */ if ((s = strrchr(path, DEFAULT_SLASH))) { if (*(s + 1) == '\0' && s != path) { /* make sure that the / is not the last character */ *s = '\0'; s = strrchr(path, DEFAULT_SLASH); } if (s) { if (s == path) { path[1] = '\0'; } else { *s = '\0'; } } } } else { /* CHECKUID_ALLOW_ONLY_DIR */ s = strrchr(filename, DEFAULT_SLASH); if (s == filename) { /* root dir */ path[0] = DEFAULT_SLASH; path[1] = '\0'; } else if (s && *(s + 1) != '\0') { /* make sure that the / is not the last character */ *s = '\0'; VCWD_REALPATH(filename, path); *s = DEFAULT_SLASH; } else { /* Under Solaris, getcwd() can fail if there are no * read permissions on a component of the path, even * though it has the required x permissions */ path[0] = '.'; path[1] = '\0'; VCWD_GETCWD(path, sizeof(path)); } } /* end CHECKUID_ALLOW_ONLY_DIR */ if (mode != CHECKUID_ALLOW_ONLY_FILE) { /* check directory */ ret = VCWD_STAT(path, &sb); if (ret < 0) { if ((flags & CHECKUID_NO_ERRORS) == 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to access %s", filename); } return 0; } duid = sb.st_uid; dgid = sb.st_gid; if (duid == php_getuid()) { return 1; } else if (PG(safe_mode_gid) && dgid == php_getgid()) { return 1; } else { if (SG(rfc1867_uploaded_files)) { if (zend_hash_exists(SG(rfc1867_uploaded_files), (char *) filename, strlen(filename)+1)) { return 1; } } } } if (mode == CHECKUID_ALLOW_ONLY_DIR) { uid = duid; gid = dgid; if (s) { *s = 0; } } if (nofile) { uid = duid; gid = dgid; filename = path; } if ((flags & CHECKUID_NO_ERRORS) == 0) { if (PG(safe_mode_gid)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE Restriction in effect. The script whose uid/gid is %ld/%ld is not allowed to access %s owned by uid/gid %ld/%ld", php_getuid(), php_getgid(), filename, uid, gid); } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SAFE MODE Restriction in effect. The script whose uid is %ld is not allowed to access %s owned by uid %ld", php_getuid(), filename, uid); } } return 0; }