📄 gsi_socket.c
字号:
/* * gsi_socket.c * * See gsi_socket.h for documentation. */#include "myproxy_common.h"struct _gsi_socket { int sock; int allow_anonymous; /* Boolean */ /* All these variables together indicate the last error we saw */ char *error_string; int error_number; gss_ctx_id_t gss_context; OM_uint32 major_status; OM_uint32 minor_status; char *peer_name;};#define DEFAULT_SERVICE_NAME "host"/********************************************************************* * * Internal functions * *//* * append_gss_status() * * Given a gssapi status and and indicator (gssapi error or mechanism- * specific error), append the errors strings to the given string. * * Returns number of bytes written to buffer, -1 if error was truncated * because the buffer was too small. */static intappend_gss_status(char *buffer, int bufferlen, const OM_uint32 gss_code, const int type){ OM_uint32 min_stat; gss_buffer_desc error_string; OM_uint32 context = 0; int total_chars = 0; int chars; assert(buffer != NULL); do { gss_display_status(&min_stat, gss_code, type, GSS_C_NULL_OID, &context, &error_string); if ((error_string.value != NULL) && (error_string.length > 0)) { chars = my_strncpy(buffer, error_string.value, bufferlen); if (chars == -1) { return -1; } total_chars += chars; buffer = &buffer[chars]; bufferlen -= chars; } (void) gss_release_buffer(&min_stat, &error_string); } while(context); return total_chars;}/* * read_all() * * Read all the requested bytes into the requested buffer. */static intread_all(const int sock, char *buffer, const int nbytes){ int total_bytes_read = 0; int bytes_read; assert(buffer != NULL); while (total_bytes_read < nbytes) { bytes_read = read(sock, &buffer[total_bytes_read], nbytes - total_bytes_read); if (bytes_read == -1) { return -1; } if (bytes_read == 0) { /* EOF */ errno = EPIPE; return -1; } total_bytes_read += bytes_read; } return total_bytes_read;}/* * write_all() * * Write all the requested bytes to the given socket. */static intwrite_all(const int sock, const char *buffer, const int nbytes){ int total_bytes_written = 0; int bytes_written; assert(buffer != NULL); while (total_bytes_written < nbytes) { bytes_written = write(sock, &buffer[total_bytes_written], nbytes - total_bytes_written); if (bytes_written == -1) { return -1; } if (bytes_written == 0) { /* EOF */ errno = EPIPE; return -1; } total_bytes_written += bytes_written; } return total_bytes_written;}/* * read_token() * * Read and allocate a token from the given socket. */static intread_token(const int sock, char **p_buffer){ enum header_fields { flag = 0, major_version = 1, minor_version = 2, length_high_byte = 3, length_low_byte = 4 }; int tot_buffer_len=0, retval; assert(p_buffer != NULL); *p_buffer = NULL; do { unsigned char header[5]; char *bufferp; int data_len, buffer_len; fd_set rfds; struct timeval tv = { 0 }; if (read_all(sock, (char *)header, sizeof(header)) < 0) { if (errno == EPIPE && tot_buffer_len > 0) goto done; return -1; } /* * Check and make sure token looks right */ if (((header[flag] < 20) || (header[flag] > 26)) || (header[major_version] != 3) || ((header[minor_version] != 0) && (header[minor_version] != 1))) { errno = EINVAL; return -1; } data_len = (header[length_high_byte] << 8) + header[length_low_byte]; buffer_len = data_len + sizeof(header); bufferp = *p_buffer = realloc(*p_buffer, tot_buffer_len+buffer_len); if (bufferp == NULL) { if (*p_buffer != NULL) { free(*p_buffer); *p_buffer = NULL; } return -1; } bufferp += tot_buffer_len; tot_buffer_len += buffer_len; memcpy(bufferp, header, sizeof(header)); bufferp += sizeof(header); if (read_all(sock, bufferp, data_len) < 0) { free(*p_buffer); *p_buffer = NULL; return -1; } /* Check for more data on the socket. We want the entire message and SSL may have fragmented it. */ FD_ZERO(&rfds); FD_SET(sock, &rfds); retval = select(sock+1, &rfds, NULL, NULL, &tv); if (retval < 0) { free(*p_buffer); *p_buffer = NULL; return -1; } } while (retval == 1); done: return tot_buffer_len;}/* * write_token() * * Write a token to the the given socket. * * Returns 0 on success, -1 on error. */static intwrite_token(const int sock, const char *buffer, const size_t buffer_size){ int return_value; assert(buffer != NULL); return_value = write_all(sock, buffer, buffer_size); return (return_value == -1 ? -1 : 0);}static intassist_write_token(void *sock, void *buffer, size_t buffer_size){ assert(sock != NULL); assert(buffer != NULL); return write_token(*((int *) sock), (char *) buffer, buffer_size);}/* * GSI_SOCKET_set_error_from_verror() * * Set the given GSI_SOCKET's error state from verror. */static voidGSI_SOCKET_set_error_from_verror(GSI_SOCKET *self){ char *string; if (verror_is_error() == 0) { return; } string = verror_get_string(); if (string != NULL) { self->error_string = strdup(string); } self->error_number = verror_get_errno();} /********************************************************************* * * API Functions * */GSI_SOCKET *GSI_SOCKET_new(int sock){ GSI_SOCKET *self = NULL; self = malloc(sizeof(GSI_SOCKET)); if (self == NULL) { return NULL; } memset(self, 0, sizeof(GSI_SOCKET)); self->gss_context = GSS_C_NO_CONTEXT; self->sock = sock; globus_module_activate(GLOBUS_GSI_GSS_ASSIST_MODULE); globus_module_activate(GLOBUS_GSI_SYSCONFIG_MODULE); return self;}voidGSI_SOCKET_destroy(GSI_SOCKET *self){ if (self == NULL) { return; } if (self->gss_context != GSS_C_NO_CONTEXT) { gss_buffer_desc output_token_desc = GSS_C_EMPTY_BUFFER; gss_delete_sec_context(&self->minor_status, &self->gss_context, &output_token_desc); /* XXX Should deal with output_token_desc here */ gss_release_buffer(&self->minor_status, &output_token_desc); } if (self->peer_name != NULL) { free(self->peer_name); } if (self->error_string) { free(self->error_string); } free(self); globus_module_deactivate(GLOBUS_GSI_GSS_ASSIST_MODULE);}intGSI_SOCKET_get_error_string(GSI_SOCKET *self, char *buffer, int bufferlen){ int total_chars = 0; int chars; if ((buffer == NULL) || (bufferlen == 0)) { /* Punt */ return -1; } if (self == NULL) { return my_strncpy(buffer, "GSI SOCKET not initialized", bufferlen); } if (self->error_string != NULL) { chars = my_strncpy(buffer, self->error_string, bufferlen-1); if (chars == -1) { goto truncated; } total_chars += chars; buffer = &buffer[chars]; bufferlen -= chars; } if (self->error_number != 0) { if (total_chars && bufferlen && *(buffer-1) != '\n') { *buffer = '\n'; buffer++; total_chars++; bufferlen--; } chars = my_strncpy(buffer, strerror(self->error_number), bufferlen); if (chars == -1) { goto truncated; } total_chars += chars; buffer = &buffer[chars]; bufferlen -= chars; } if (self->major_status) { if (total_chars && bufferlen && *(buffer-1) != '\n') { *buffer = '\n'; buffer++; total_chars++; bufferlen--; } chars = append_gss_status(buffer, bufferlen, self->major_status, GSS_C_GSS_CODE); if (chars == -1) { goto truncated; } total_chars += chars; buffer = &buffer[chars]; bufferlen -= chars; chars = append_gss_status(buffer, bufferlen, self->minor_status, GSS_C_MECH_CODE); if (chars == -1) { goto truncated; } total_chars += chars; buffer = &buffer[chars]; bufferlen -= chars; /* Parse errors from gss-assist routines */ chars = 0; switch(self->major_status) { case GSS_S_DEFECTIVE_TOKEN | GSS_S_CALL_INACCESSIBLE_READ: chars = my_strncpy(buffer, "Error reading token", bufferlen); break; case GSS_S_DEFECTIVE_TOKEN | GSS_S_CALL_INACCESSIBLE_WRITE: chars = my_strncpy(buffer, "Error writing token", bufferlen); break; } total_chars += chars; buffer = &buffer[chars]; bufferlen -= chars; } if (total_chars == 0) { /* No error */ buffer[0] = '\0'; } return total_chars; truncated: return -1;}voidGSI_SOCKET_clear_error(GSI_SOCKET *self){ if (self == NULL) { return; } if (self->error_string != NULL) { free(self->error_string); self->error_string = NULL; } self->error_number = 0; self->major_status = 0; self->minor_status = 0;}intGSI_SOCKET_allow_anonymous(GSI_SOCKET *self, const int value){ if (self == NULL) { return GSI_SOCKET_ERROR; } self->allow_anonymous = value; return GSI_SOCKET_SUCCESS;}/* XXX This routine really needs a complete overhaul */intGSI_SOCKET_use_creds(GSI_SOCKET *self, const char *creds){ int return_code = GSI_SOCKET_ERROR; if (creds == NULL) { /* XXX Do nothing for now */ return_code = GSI_SOCKET_SUCCESS; } else { unsetenv("X509_USER_CERT"); unsetenv("X509_USER_KEY"); return_code = (setenv("X509_USER_PROXY", creds, 1) == -1) ? GSI_SOCKET_ERROR : GSI_SOCKET_SUCCESS; } return return_code;}intGSI_SOCKET_check_creds(GSI_SOCKET *self)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -