📄 gsi_socket.c
字号:
{ gss_cred_id_t creds = GSS_C_NO_CREDENTIAL; int return_value = GSI_SOCKET_ERROR; if (self == NULL) { return GSI_SOCKET_ERROR; } self->major_status = globus_gss_assist_acquire_cred(&self->minor_status, GSS_C_BOTH, &creds); if (self->major_status != GSS_S_COMPLETE) { goto error; } /* Success */ return_value = GSI_SOCKET_SUCCESS; error: if (creds != GSS_C_NO_CREDENTIAL) { OM_uint32 minor_status; gss_release_cred(&minor_status, &creds); } return return_value;}intGSI_SOCKET_authentication_init(GSI_SOCKET *self, char *accepted_peer_names[]){ int token_status; gss_cred_id_t creds = GSS_C_NO_CREDENTIAL; gss_name_t server_gss_name = GSS_C_NO_NAME; OM_uint32 req_flags = 0, ret_flags = 0; int return_value = GSI_SOCKET_ERROR; gss_buffer_desc gss_buffer = { 0 }, tmp_gss_buffer = { 0 }; gss_name_t target_name = GSS_C_NO_NAME; gss_OID target_name_type = GSS_C_NO_OID; int i, rc=0, sock; FILE *fp = NULL; char *cert_dir = NULL; if (self == NULL) { return GSI_SOCKET_ERROR; } if (accepted_peer_names == NULL || accepted_peer_names[0] == NULL) { return GSI_SOCKET_ERROR; } if (self->gss_context != GSS_C_NO_CONTEXT) { self->error_string = strdup("GSI_SOCKET already authenticated"); goto error; } GLOBUS_GSI_SYSCONFIG_GET_CERT_DIR(&cert_dir); if (cert_dir) { myproxy_debug("using trusted certificates directory %s", cert_dir); } else { myproxy_debug("error getting trusted certificates directory"); } self->major_status = globus_gss_assist_acquire_cred(&self->minor_status, GSS_C_INITIATE, &creds); if (self->major_status != GSS_S_COMPLETE) { if (self->allow_anonymous) { req_flags |= GSS_C_ANON_FLAG; } else { goto error; } } req_flags |= GSS_C_REPLAY_FLAG; req_flags |= GSS_C_MUTUAL_FLAG; req_flags |= GSS_C_CONF_FLAG; req_flags |= GSS_C_INTEG_FLAG; if ((sock = dup(self->sock)) < 0) { self->error_string = strdup("dup() of socket fd failed"); self->error_number = errno; goto error; } if ((fp = fdopen(sock, "r")) == NULL) { self->error_string = strdup("fdopen() of socket failed"); self->error_number = errno; goto error; } if (setvbuf(fp, NULL, _IONBF, 0) != 0) { self->error_string = strdup("setvbuf() for socket failed"); self->error_number = errno; goto error; } self->major_status = globus_gss_assist_init_sec_context(&self->minor_status, creds, &self->gss_context, "GSI-NO-TARGET", req_flags, &ret_flags, &token_status, globus_gss_assist_token_get_fd, (void *)fp, assist_write_token, (void *)&self->sock); if (self->major_status != GSS_S_COMPLETE) { goto error; } /* Verify that all service requests were honored. */ req_flags &= ~(GSS_C_ANON_FLAG); /* GSI GSSAPI doesn't set this flag */ if ((req_flags & ret_flags) != req_flags) { self->error_string = strdup("requested GSSAPI service not supported"); goto error; } /* Check the authenticated identity of the server. */ self->major_status = gss_inquire_context(&self->minor_status, self->gss_context, NULL, &server_gss_name, NULL, NULL, NULL, NULL, NULL); if (self->major_status != GSS_S_COMPLETE) { self->error_string = strdup("gss_inquire_context() failed"); goto error; } self->major_status = gss_display_name(&self->minor_status, server_gss_name, &gss_buffer, NULL); if (self->major_status != GSS_S_COMPLETE) { self->error_string = strdup("gss_display_name() failed"); goto error; } self->peer_name = strdup(gss_buffer.value); myproxy_debug("server name: %s", self->peer_name); /* We told gss_assist_init_sec_context() not to check the server name so we can check it manually here. */ for (i=0; accepted_peer_names[i] != NULL; i++) { myproxy_debug("checking if server name matches \"%s\"", accepted_peer_names[i]); tmp_gss_buffer.value = (void *)accepted_peer_names[i]; tmp_gss_buffer.length = strlen(accepted_peer_names[i]); if (strchr(accepted_peer_names[i],'@') && !strstr(accepted_peer_names[i],"CN=")) { target_name_type = GSS_C_NT_HOSTBASED_SERVICE; } else { target_name_type = GSS_C_NO_OID; } self->major_status = gss_import_name(&self->minor_status, &tmp_gss_buffer, target_name_type, &target_name); if (self->major_status != GSS_S_COMPLETE) { char error_string[550]; sprintf(error_string, "failed to import GSS name \"%.500s\"", accepted_peer_names[i]); self->error_string = strdup(error_string); goto error; } self->major_status = gss_compare_name(&self->minor_status, server_gss_name, target_name, &rc); gss_release_name(&self->minor_status, &target_name); if (self->major_status != GSS_S_COMPLETE) { char error_string[1050]; sprintf(error_string, "gss_compare_name(\"%.500s\",\"%.500s\") failed", self->peer_name, accepted_peer_names[i]); self->error_string = strdup(error_string); goto error; } if (rc) { myproxy_debug("server name accepted"); break; } else { myproxy_debug("server name does not match"); } } if (!rc) { /* no match with acceptable target names */ self->error_string = strdup("authenticated peer name does not match"); return_value = GSI_SOCKET_UNAUTHORIZED; goto error; } /* Success */ return_value = GSI_SOCKET_SUCCESS; error: { OM_uint32 minor_status; gss_release_cred(&minor_status, &creds); gss_release_buffer(&minor_status, &gss_buffer); gss_release_name(&minor_status, &server_gss_name); } if (cert_dir) free(cert_dir); if (fp) fclose(fp); return return_value;}intGSI_SOCKET_authentication_accept(GSI_SOCKET *self){ gss_cred_id_t creds = GSS_C_NO_CREDENTIAL; int token_status; int return_value = GSI_SOCKET_ERROR; OM_uint32 gss_flags = 0; int sock; FILE *fp = NULL; char *cert_dir = NULL; if (self == NULL) { return GSI_SOCKET_ERROR; } if (self->gss_context != GSS_C_NO_CONTEXT) { self->error_string = strdup("GSI_SOCKET already authenticated"); goto error; } GLOBUS_GSI_SYSCONFIG_GET_CERT_DIR(&cert_dir); if (cert_dir) { myproxy_debug("using trusted certificates directory %s", cert_dir); } else { myproxy_debug("error getting trusted certificates directory"); } self->major_status = globus_gss_assist_acquire_cred(&self->minor_status, GSS_C_ACCEPT, &creds); if (self->major_status != GSS_S_COMPLETE) { goto error; } /* These are supposed to be return flags only, according to RFC 2774, but GSI helpfully uses them as request flags too. */ gss_flags |= GSS_C_ANON_FLAG; gss_flags |= GSS_C_REPLAY_FLAG; gss_flags |= GSS_C_MUTUAL_FLAG; gss_flags |= GSS_C_CONF_FLAG; gss_flags |= GSS_C_INTEG_FLAG; if ((sock = dup(self->sock)) < 0) { self->error_string = strdup("dup() of socket fd failed"); self->error_number = errno; goto error; } if ((fp = fdopen(sock, "r")) == NULL) { self->error_string = strdup("fdopen() of socket failed"); self->error_number = errno; goto error; } if (setvbuf(fp, NULL, _IONBF, 0) != 0) { self->error_string = strdup("setvbuf() for socket failed"); self->error_number = errno; goto error; } self->major_status = globus_gss_assist_accept_sec_context(&self->minor_status, &self->gss_context, creds, &self->peer_name, &gss_flags, NULL, /* u2u flag */ &token_status, NULL, /* Delegated creds * added in Globus 1.1.3 */ globus_gss_assist_token_get_fd, (void *)fp, assist_write_token, (void *)&self->sock); if (self->major_status != GSS_S_COMPLETE) { goto error; } /* Success */ return_value = GSI_SOCKET_SUCCESS; error: if (creds != GSS_C_NO_CREDENTIAL) { OM_uint32 minor_status; gss_release_cred(&minor_status, &creds); } if (cert_dir) free(cert_dir); if (fp) fclose(fp); return return_value;}intGSI_SOCKET_get_peer_name(GSI_SOCKET *self, char *buffer, const int buffer_len){ int return_value = GSI_SOCKET_ERROR; if (self == NULL) { return GSI_SOCKET_ERROR; } if (buffer == NULL) { self->error_number = EINVAL; return GSI_SOCKET_ERROR; } if (self->peer_name == NULL) { self->error_string = strdup("Client not authenticated"); goto error; } return_value = my_strncpy(buffer, self->peer_name, buffer_len); if (return_value == -1) { return_value = GSI_SOCKET_TRUNCATED; goto error; } /* SUCCESS */ return_value = GSI_SOCKET_SUCCESS; error: return return_value;}char *GSI_SOCKET_get_peer_hostname(GSI_SOCKET *self){ struct sockaddr_in addr; socklen_t addr_len = sizeof(addr); struct hostent *info; if (getpeername(self->sock, (struct sockaddr *) &addr, &addr_len) < 0) { self->error_number = errno; self->error_string = strdup("Could not get peer address"); return NULL; } info = gethostbyaddr((char *)&addr.sin_addr, sizeof(addr.sin_addr), addr.sin_family); if ((info == NULL) || (info->h_name == NULL)) { self->error_number = errno; self->error_string = strdup("Could not get peer hostname"); return NULL; } if (info->h_addrtype == AF_INET) { /* check for localhost */ struct in_addr inaddr; inaddr = *(struct in_addr *)(info->h_addr); if (ntohl(inaddr.s_addr) == INADDR_LOOPBACK) { char buf[MAXHOSTNAMELEN]; if (gethostname(buf, sizeof(buf)) < 0) { self->error_number = errno; self->error_string = strdup("gethostname() failed"); return NULL; } info = gethostbyname(buf); if (info == NULL || info->h_name == NULL) { return strdup(buf); } } } return strdup(info->h_name);}intGSI_SOCKET_write_buffer(GSI_SOCKET *self, const char *buffer, const size_t buffer_len){ int return_value = GSI_SOCKET_ERROR; if (self == NULL) { return GSI_SOCKET_ERROR; } #if 0 if (buffer[buffer_len-1] == '\0') { myproxy_debug("writing a null-terminated message"); } else { myproxy_debug("writing a non-null-terminated message"); }#endif if ((buffer == NULL) || (buffer_len == 0)) { return 0; } if (self->gss_context == GSS_C_NO_CONTEXT) { /* No context established, just send in the clear */ return_value = write_token(self->sock, buffer, buffer_len); if (return_value == -1) { self->error_number = errno; self->error_string = strdup("failed to write token"); goto error; } } else { /* Encrypt buffer before sending */ gss_buffer_desc unwrapped_buffer; gss_buffer_desc wrapped_buffer; int conf_state; unwrapped_buffer.value = (char *) buffer; unwrapped_buffer.length = buffer_len; self->major_status = gss_wrap(&self->minor_status, self->gss_context, 1 /* encrypt */, GSS_C_QOP_DEFAULT, &unwrapped_buffer, &conf_state, &wrapped_buffer); if (self->major_status != GSS_S_COMPLETE) { goto error; } if (!conf_state) { self->error_string = strdup("GSI_SOCKET failed to encrypt"); goto error; } return_value = write_token(self->sock, wrapped_buffer.value, wrapped_buffer.length); if (return_value == -1) { self->error_number = errno; self->error_string = strdup("failed to write token"); gss_release_buffer(&self->minor_status, &wrapped_buffer); goto error; } gss_release_buffer(&self->minor_status, &wrapped_buffer); } /* myproxy_debug("\nwrote:\n%s\n", buffer); */ error: return return_value;}staticsize_t safe_strlen(const char s[], size_t bufsiz){ int i; for (i=0; i < bufsiz; i++) { if (s[i] == '\0') { return i; } } return i;}int GSI_SOCKET_read_token(GSI_SOCKET *self, unsigned char **pbuffer, size_t *pbuffer_len){ int bytes_read; static unsigned char *saved_buffer = NULL; /* not thread safe! */ static int saved_buffer_len = 0; unsigned char *buffer; int return_status = GSI_SOCKET_ERROR; if (saved_buffer) { buffer = saved_buffer; bytes_read = saved_buffer_len; saved_buffer = NULL; saved_buffer_len = 0; } else { bytes_read = read_token(self->sock, (char **) &buffer); if (bytes_read == -1) { self->error_number = errno; self->error_string = strdup("failed to read token"); goto error; } if (self->gss_context != GSS_C_NO_CONTEXT) { /* Need to unwrap read data */ gss_buffer_desc unwrapped_buffer; gss_buffer_desc wrapped_buffer; int conf_state; gss_qop_t qop_state; wrapped_buffer.value = buffer; wrapped_buffer.length = bytes_read; self->major_status = gss_unwrap(&self->minor_status, self->gss_context, &wrapped_buffer, &unwrapped_buffer, &conf_state, &qop_state); free(buffer); if (self->major_status != GSS_S_COMPLETE) { goto error;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -