struct ne_lock *ne_lockstore_findbyuri(ne_lock_store *store, const ne_uri *uri) { struct lock_list *cur; for (cur = store->locks; cur != NULL; cur = cur->next) { if (ne_uri_cmp(&cur->lock->uri, uri) == 0) { return cur->lock; } } return NULL; }
void ne_lock_using_parent(ne_request *req, const char *path) { NE_DEBUG_WINSCP_CONTEXT(ne_get_session(req)); struct lh_req_cookie *lrc = ne_get_request_private(req, HOOK_ID); ne_uri u = {0}; struct lock_list *item; char *parent; if (lrc == NULL) return; parent = ne_path_parent(path); if (parent == NULL) return; ne_fill_server_uri(ne_get_session(req), &u); for (item = lrc->store->locks; item != NULL; item = item->next) { /* Only care about locks which are on this server. */ u.path = item->lock->uri.path; if (ne_uri_cmp(&u, &item->lock->uri)) continue; /* This lock is needed if it is an infinite depth lock which * covers the parent, or a lock on the parent itself. */ if ((item->lock->depth == NE_DEPTH_INFINITE && ne_path_childof(item->lock->uri.path, parent)) || ne_path_compare(item->lock->uri.path, parent) == 0) { NE_DEBUG(NE_DBG_LOCKS, "Locked parent, %s on %s\n", item->lock->token, item->lock->uri.path); submit_lock(lrc, item->lock); } } u.path = parent; /* handy: makes u.path valid and ne_free(parent). */ ne_uri_free(&u); }
/* Check certificate identity. Returns zero if identity matches; 1 if * identity does not match, or <0 if the certificate had no identity. * If 'identity' is non-NULL, store the malloc-allocated identity in * *identity. Logic specified by RFC 2818 and RFC 3280. */ static int check_identity(const ne_uri *server, X509 *cert, char **identity) { STACK_OF(GENERAL_NAME) *names; int match = 0, found = 0; const char *hostname; hostname = server ? server->host : ""; names = X509_get_ext_d2i(cert, NID_subject_alt_name, NULL, NULL); if (names) { int n; /* subjectAltName contains a sequence of GeneralNames */ for (n = 0; n < sk_GENERAL_NAME_num(names) && !match; n++) { GENERAL_NAME *nm = sk_GENERAL_NAME_value(names, n); /* handle dNSName and iPAddress name extensions only. */ if (nm->type == GEN_DNS) { char *name = dup_ia5string(nm->d.ia5); if (identity && !found) *identity = ne_strdup(name); match = ne__ssl_match_hostname(name, strlen(name), hostname); free(name); found = 1; } else if (nm->type == GEN_IPADD) { /* compare IP address with server IP address. */ ne_inet_addr *ia; if (nm->d.ip->length == 4) ia = ne_iaddr_make(ne_iaddr_ipv4, nm->d.ip->data); else if (nm->d.ip->length == 16) ia = ne_iaddr_make(ne_iaddr_ipv6, nm->d.ip->data); else ia = NULL; /* ne_iaddr_make returns NULL if address type is unsupported */ if (ia != NULL) { /* address type was supported. */ char buf[128]; match = strcmp(hostname, ne_iaddr_print(ia, buf, sizeof buf)) == 0; found = 1; ne_iaddr_free(ia); } else { NE_DEBUG(NE_DBG_SSL, "iPAddress name with unsupported " "address type (length %d), skipped.\n", nm->d.ip->length); } } else if (nm->type == GEN_URI) { char *name = dup_ia5string(nm->d.ia5); ne_uri uri; if (ne_uri_parse(name, &uri) == 0 && uri.host && uri.scheme) { ne_uri tmp; if (identity && !found) *identity = ne_strdup(name); found = 1; if (server) { /* For comparison purposes, all that matters is * host, scheme and port; ignore the rest. */ memset(&tmp, 0, sizeof tmp); tmp.host = uri.host; tmp.scheme = uri.scheme; tmp.port = uri.port; match = ne_uri_cmp(server, &tmp) == 0; } } ne_uri_free(&uri); free(name); } } /* free the whole stack. */ sk_GENERAL_NAME_pop_free(names, GENERAL_NAME_free); } /* Check against the commonName if no DNS alt. names were found, * as per RFC3280. */ if (!found) { X509_NAME *subj = X509_get_subject_name(cert); X509_NAME_ENTRY *entry; ne_buffer *cname = ne_buffer_ncreate(30); int idx = -1, lastidx; /* find the most specific commonName attribute. */ do { lastidx = idx; idx = X509_NAME_get_index_by_NID(subj, NID_commonName, lastidx); } while (idx >= 0); if (lastidx < 0) { /* no commonName attributes at all. */ ne_buffer_destroy(cname); return -1; } /* extract the string from the entry */ entry = X509_NAME_get_entry(subj, lastidx); if (append_dirstring(cname, X509_NAME_ENTRY_get_data(entry))) { ne_buffer_destroy(cname); return -1; } if (identity) *identity = ne_strdup(cname->data); match = ne__ssl_match_hostname(cname->data, cname->used - 1, hostname); ne_buffer_destroy(cname); } NE_DEBUG(NE_DBG_SSL, "Identity match for '%s': %s\n", hostname, match ? "good" : "bad"); return match ? 0 : 1; }
/* Check certificate identity. Returns zero if identity matches; 1 if * identity does not match, or <0 if the certificate had no identity. * If 'identity' is non-NULL, store the malloc-allocated identity in * *identity. If 'server' is non-NULL, it must be the network address * of the server in use, and identity must be NULL. */ static int check_identity(const ne_uri *server, gnutls_x509_crt cert, char **identity) { char name[255]; unsigned int critical; int ret, seq = 0; int match = 0, found = 0; size_t len; const char *hostname; hostname = server ? server->host : ""; do { len = sizeof name - 1; ret = gnutls_x509_crt_get_subject_alt_name(cert, seq, name, &len, &critical); switch (ret) { case GNUTLS_SAN_DNSNAME: name[len] = '\0'; if (identity && !found) *identity = ne_strdup(name); match = ne__ssl_match_hostname(name, len, hostname); found = 1; break; case GNUTLS_SAN_IPADDRESS: { ne_inet_addr *ia; if (len == 4) ia = ne_iaddr_make(ne_iaddr_ipv4, (unsigned char *)name); else if (len == 16) ia = ne_iaddr_make(ne_iaddr_ipv6, (unsigned char *)name); else ia = NULL; if (ia) { char buf[128]; match = strcmp(hostname, ne_iaddr_print(ia, buf, sizeof buf)) == 0; if (identity) *identity = ne_strdup(buf); found = 1; ne_iaddr_free(ia); } else { NE_DEBUG(NE_DBG_SSL, "iPAddress name with unsupported " "address type (length %" NE_FMT_SIZE_T "), skipped.\n", len); } } break; case GNUTLS_SAN_URI: { ne_uri uri; name[len] = '\0'; if (ne_uri_parse(name, &uri) == 0 && uri.host && uri.scheme) { ne_uri tmp; if (identity && !found) *identity = ne_strdup(name); found = 1; if (server) { /* For comparison purposes, all that matters is * host, scheme and port; ignore the rest. */ memset(&tmp, 0, sizeof tmp); tmp.host = uri.host; tmp.scheme = uri.scheme; tmp.port = uri.port; match = ne_uri_cmp(server, &tmp) == 0; } } ne_uri_free(&uri); } break; default: break; } seq++; } while (!match && ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); /* Check against the commonName if no DNS alt. names were found, * as per RFC3280. */ if (!found) { seq = oid_find_highest_index(cert, 1, GNUTLS_OID_X520_COMMON_NAME); if (seq >= 0) { len = sizeof name; name[0] = '\0'; ret = gnutls_x509_crt_get_dn_by_oid(cert, GNUTLS_OID_X520_COMMON_NAME, seq, 0, name, &len); if (ret == 0) { if (identity) *identity = ne_strdup(name); match = ne__ssl_match_hostname(name, len, hostname); } } else { return -1; } } if (*hostname) NE_DEBUG(NE_DBG_SSL, "ssl: Identity match for '%s': %s\n", hostname, match ? "good" : "bad"); return match ? 0 : 1; }