aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/security/credentials.c6
-rw-r--r--src/core/security/security_context.c46
-rw-r--r--src/core/support/env.h60
-rw-r--r--src/core/support/env_linux.c61
-rw-r--r--src/core/support/env_posix.c56
-rw-r--r--src/core/support/env_win32.c60
-rw-r--r--src/core/support/file.c89
-rw-r--r--src/core/support/file.h61
-rw-r--r--src/core/support/file_posix.c97
-rw-r--r--src/core/support/file_win32.c78
10 files changed, 603 insertions, 11 deletions
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 7b7d8f3211..6f0d72c0c3 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -216,14 +216,10 @@ static void ssl_copy_key_material(const char *input, unsigned char **output,
static void ssl_build_config(const char *pem_root_certs,
grpc_ssl_pem_key_cert_pair *pem_key_cert_pair,
grpc_ssl_config *config) {
- if (pem_root_certs == NULL) {
- /* TODO(jboeuf): Get them from the environment. */
- gpr_log(GPR_ERROR, "Default SSL roots not yet implemented.");
- } else {
+ if (pem_root_certs != NULL) {
ssl_copy_key_material(pem_root_certs, &config->pem_root_certs,
&config->pem_root_certs_size);
}
-
if (pem_key_cert_pair != NULL) {
GPR_ASSERT(pem_key_cert_pair->private_key != NULL);
GPR_ASSERT(pem_key_cert_pair->cert_chain != NULL);
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
index 58cd458415..1edec29775 100644
--- a/src/core/security/security_context.c
+++ b/src/core/security/security_context.c
@@ -39,6 +39,8 @@
#include "src/core/channel/http_client_filter.h"
#include "src/core/security/credentials.h"
#include "src/core/security/secure_endpoint.h"
+#include "src/core/support/env.h"
+#include "src/core/support/file.h"
#include "src/core/support/string.h"
#include "src/core/surface/lame_client.h"
#include "src/core/transport/chttp2/alpn.h"
@@ -319,6 +321,28 @@ static grpc_security_context_vtable ssl_channel_vtable = {
static grpc_security_context_vtable ssl_server_vtable = {
ssl_server_destroy, ssl_server_create_handshaker, ssl_server_check_peer};
+static gpr_slice default_pem_root_certs;
+
+static void init_default_pem_root_certs(void) {
+ char *default_root_certs_path =
+ gpr_getenv(GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR);
+ if (default_root_certs_path == NULL) {
+ default_pem_root_certs = gpr_empty_slice();
+ } else {
+ default_pem_root_certs = gpr_load_file(default_root_certs_path, NULL);
+ gpr_free(default_root_certs_path);
+ }
+}
+
+static size_t get_default_pem_roots(const unsigned char **pem_root_certs) {
+ /* TODO(jboeuf@google.com): Maybe revisit the approach which consists in
+ loading all the roots once for the lifetime of the process. */
+ static gpr_once once = GPR_ONCE_INIT;
+ gpr_once_init(&once, init_default_pem_root_certs);
+ *pem_root_certs = GPR_SLICE_START_PTR(default_pem_root_certs);
+ return GPR_SLICE_LENGTH(default_pem_root_certs);
+}
+
grpc_security_status grpc_ssl_channel_security_context_create(
grpc_credentials *request_metadata_creds, const grpc_ssl_config *config,
const char *secure_peer_name, grpc_channel_security_context **ctx) {
@@ -330,6 +354,8 @@ grpc_security_status grpc_ssl_channel_security_context_create(
tsi_result result = TSI_OK;
grpc_ssl_channel_security_context *c;
size_t i;
+ const unsigned char *pem_root_certs;
+ size_t pem_root_certs_size;
for (i = 0; i < num_alpn_protocols; i++) {
alpn_protocol_strings[i] =
@@ -338,9 +364,8 @@ grpc_security_status grpc_ssl_channel_security_context_create(
strlen(grpc_chttp2_get_alpn_version_index(i));
}
- if (config == NULL || secure_peer_name == NULL ||
- config->pem_root_certs == NULL) {
- gpr_log(GPR_ERROR, "An ssl channel needs a secure name and root certs.");
+ if (config == NULL || secure_peer_name == NULL) {
+ gpr_log(GPR_ERROR, "An ssl channel needs a config and a secure name.");
goto error;
}
if (!check_request_metadata_creds(request_metadata_creds)) {
@@ -357,11 +382,20 @@ grpc_security_status grpc_ssl_channel_security_context_create(
if (secure_peer_name != NULL) {
c->secure_peer_name = gpr_strdup(secure_peer_name);
}
+ if (config->pem_root_certs == NULL) {
+ pem_root_certs_size = get_default_pem_roots(&pem_root_certs);
+ if (pem_root_certs == NULL || pem_root_certs_size == 0) {
+ gpr_log(GPR_ERROR, "Could not get default pem root certs.");
+ goto error;
+ }
+ } else {
+ pem_root_certs = config->pem_root_certs;
+ pem_root_certs_size = config->pem_root_certs_size;
+ }
result = tsi_create_ssl_client_handshaker_factory(
config->pem_private_key, config->pem_private_key_size,
- config->pem_cert_chain, config->pem_cert_chain_size,
- config->pem_root_certs, config->pem_root_certs_size,
- GRPC_SSL_CIPHER_SUITES, alpn_protocol_strings,
+ config->pem_cert_chain, config->pem_cert_chain_size, pem_root_certs,
+ pem_root_certs_size, GRPC_SSL_CIPHER_SUITES, alpn_protocol_strings,
alpn_protocol_string_lengths, num_alpn_protocols, &c->handshaker_factory);
if (result != TSI_OK) {
gpr_log(GPR_ERROR, "Handshaker factory creation failed with %s.",
diff --git a/src/core/support/env.h b/src/core/support/env.h
new file mode 100644
index 0000000000..81dda7d838
--- /dev/null
+++ b/src/core/support/env.h
@@ -0,0 +1,60 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GRPC_SUPPORT_ENV_H__
+#define __GRPC_SUPPORT_ENV_H__
+
+#include <stdio.h>
+
+#include <grpc/support/slice.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Env utility functions */
+
+/* Gets the environment variable value with the specified name.
+ Returns a newly allocated string. It is the responsability of the caller to
+ gpr_free the return value if not NULL (which means that the environment
+ variable exists). */
+char *gpr_getenv(const char *name);
+
+/* Sets the the environment with the specified name to the specified value. */
+void gpr_setenv(const char *name, const char *value);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GRPC_SUPPORT_ENV_H__ */
diff --git a/src/core/support/env_linux.c b/src/core/support/env_linux.c
new file mode 100644
index 0000000000..28e3d1450f
--- /dev/null
+++ b/src/core/support/env_linux.c
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* for secure_getenv. */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_LINUX_ENV
+
+#include "src/core/support/env.h"
+
+#include <stdlib.h>
+
+#include <grpc/support/log.h>
+
+#include "src/core/support/string.h"
+
+char *gpr_getenv(const char *name) {
+ char *result = secure_getenv(name);
+ return result == NULL ? result : gpr_strdup(result);
+}
+
+void gpr_setenv(const char *name, const char *value) {
+ int res = setenv(name, value, 1);
+ GPR_ASSERT(res == 0);
+}
+
+#endif /* GPR_LINUX_ENV */
diff --git a/src/core/support/env_posix.c b/src/core/support/env_posix.c
new file mode 100644
index 0000000000..bcbff9a177
--- /dev/null
+++ b/src/core/support/env_posix.c
@@ -0,0 +1,56 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_ENV
+
+#include "src/core/support/env.h"
+
+#include <stdlib.h>
+
+#include <grpc/support/log.h>
+
+#include "src/core/support/string.h"
+
+char *gpr_getenv(const char *name) {
+ char *result = getenv(name);
+ return result == NULL ? result : gpr_strdup(result);
+}
+
+void gpr_setenv(const char *name, const char *value) {
+ int res = setenv(name, value, 1);
+ GPR_ASSERT(res == 0);
+}
+
+#endif /* GPR_POSIX_ENV */
diff --git a/src/core/support/env_win32.c b/src/core/support/env_win32.c
new file mode 100644
index 0000000000..a31fa79d68
--- /dev/null
+++ b/src/core/support/env_win32.c
@@ -0,0 +1,60 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WIN32
+
+#include "src/core/support/env.h"
+
+#include <stdlib.h>
+
+#include <grpc/support/log.h>
+
+char *gpr_getenv(const char *name) {
+ size_t required_size;
+ char *result = NULL;
+
+ getenv_s(&required_size, NULL, 0, name);
+ if (required_size == 0) return NULL;
+ result = gpr_malloc(required_size);
+ getenv_s(&required_size, result, required_size, name);
+ return result;
+}
+
+void gpr_setenv(const char *name, const char *value) {
+ errno_t res = _putenv_s(name, value);
+ GPR_ASSERT(res == 0);
+}
+
+#endif /* GPR_WIN32 */
diff --git a/src/core/support/file.c b/src/core/support/file.c
new file mode 100644
index 0000000000..c0bb1b66a0
--- /dev/null
+++ b/src/core/support/file.c
@@ -0,0 +1,89 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "src/core/support/file.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/support/string.h"
+
+gpr_slice gpr_load_file(const char *filename, int *success) {
+ unsigned char *contents = NULL;
+ size_t contents_size = 0;
+ unsigned char buf[4096];
+ char *error_msg = NULL;
+ gpr_slice result = gpr_empty_slice();
+ FILE *file = fopen(filename, "rb");
+
+ if (file == NULL) {
+ gpr_asprintf(&error_msg, "Could not open file %s (error = %s).", filename,
+ strerror(errno));
+ GPR_ASSERT(error_msg != NULL);
+ goto end;
+ }
+
+ while (1) {
+ size_t bytes_read = fread(buf, 1, sizeof(buf), file);
+ if (bytes_read > 0) {
+ contents = gpr_realloc(contents, contents_size + bytes_read);
+ memcpy(contents + contents_size, buf, bytes_read);
+ contents_size += bytes_read;
+ }
+ if (bytes_read < sizeof(buf)) {
+ if (ferror(file)) {
+ gpr_asprintf(&error_msg, "Error %s occured while reading file %s.",
+ strerror(errno), filename);
+ GPR_ASSERT(error_msg != NULL);
+ goto end;
+ } else {
+ GPR_ASSERT(feof(file));
+ break;
+ }
+ }
+ }
+ if (success != NULL) *success = 1;
+ result = gpr_slice_new(contents, contents_size, gpr_free);
+
+end:
+ if (error_msg != NULL) {
+ gpr_log(GPR_ERROR, "%s", error_msg);
+ gpr_free(error_msg);
+ if (success != NULL) *success = 0;
+ }
+ if (file != NULL) fclose(file);
+ return result;
+}
diff --git a/src/core/support/file.h b/src/core/support/file.h
new file mode 100644
index 0000000000..92f420e7ce
--- /dev/null
+++ b/src/core/support/file.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GRPC_SUPPORT_FILE_H__
+#define __GRPC_SUPPORT_FILE_H__
+
+#include <stdio.h>
+
+#include <grpc/support/slice.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* File utility functions */
+
+/* Loads the content of a file into a slice. The success parameter, if not NULL,
+ will be set to 1 in case of success and 0 in case of failure. */
+gpr_slice gpr_load_file(const char *filename, int *success);
+
+/* Creates a temporary file from a prefix.
+ If tmp_filename is not NULL, *tmp_filename is assigned the name of the
+ created file and it is the responsibility of the caller to gpr_free it
+ unless an error occurs in which case it will be set to NULL. */
+FILE *gpr_tmpfile(const char *prefix, char **tmp_filename);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __GRPC_SUPPORT_FILE_H__ */
diff --git a/src/core/support/file_posix.c b/src/core/support/file_posix.c
new file mode 100644
index 0000000000..21a985012e
--- /dev/null
+++ b/src/core/support/file_posix.c
@@ -0,0 +1,97 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Posix code for gpr fdopen and mkstemp support. */
+
+#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 200112L
+#undef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200112L
+#endif
+
+/* Don't know why I have to do this for mkstemp, looks like _POSIX_C_SOURCE
+ should be enough... */
+#ifndef _BSD_SOURCE
+#define _BSD_SOURCE
+#endif
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_POSIX_FILE
+
+#include "src/core/support/file.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/support/string.h"
+
+FILE *gpr_tmpfile(const char *prefix, char **tmp_filename) {
+ FILE *result = NULL;
+ char *template;
+ int fd;
+
+ if (tmp_filename != NULL) *tmp_filename = NULL;
+
+ gpr_asprintf(&template, "%s_XXXXXX", prefix);
+ GPR_ASSERT(template != NULL);
+
+ fd = mkstemp(template);
+ if (fd == -1) {
+ gpr_log(GPR_ERROR, "mkstemp failed for template %s with error %s.",
+ template, strerror(errno));
+ goto end;
+ }
+ result = fdopen(fd, "w+");
+ if (result == NULL) {
+ gpr_log(GPR_ERROR, "Could not open file %s from fd %d (error = %s).",
+ template, fd, strerror(errno));
+ unlink(template);
+ close(fd);
+ goto end;
+ }
+
+end:
+ if (result != NULL && tmp_filename != NULL) {
+ *tmp_filename = template;
+ } else {
+ gpr_free(template);
+ }
+ return result;
+}
+
+#endif /* GPR_POSIX_FILE */
diff --git a/src/core/support/file_win32.c b/src/core/support/file_win32.c
new file mode 100644
index 0000000000..d415281e0d
--- /dev/null
+++ b/src/core/support/file_win32.c
@@ -0,0 +1,78 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WIN32
+
+#include "src/core/support/file.h"
+
+#include <io.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+FILE *gpr_tmpfile(const char *prefix, char **tmp_filename) {
+ FILE *result = NULL;
+ char *template;
+
+ if (tmp_filename != NULL) *tmp_filename = NULL;
+
+ gpr_asprintf(&template, "%s_XXXXXX", prefix);
+ GPR_ASSERT(template != NULL);
+
+ /* _mktemp_s can only create a maximum of 26 file names for any combination of
+ base and template values which is kind of sad... We may revisit this
+ function later to have something better... */
+ if (_mktemp_s(template, strlen(template) + 1) != 0) {
+ gpr_log(LOG_ERROR, "Could not create tmp file.");
+ goto end;
+ }
+ if (fopen_s(&result, template, "wb+") != 0) {
+ gpr_log(GPR_ERROR, "Could not open file %s", template);
+ result = NULL;
+ goto end;
+ }
+
+end:
+ if (result != NULL && tmp_filename != NULL) {
+ *tmp_filename = template;
+ } else {
+ gpr_free(template);
+ }
+ return result;
+}
+
+#endif /* GPR_WIN32 */