S3 *new_S3(const char *access_id,const char *secret_key) { S3 *s3; if(!access_id) return NULL; if(!secret_key) return NULL; if(strlen(access_id) > 63) return NULL; if(strlen(secret_key) > 63) return NULL; s3 = (S3 *)calloc(1,sizeof(S3)); if(!s3) { fprintf(stderr,"Could not create S3 object. Out of memory.\n"); exit(1); } strcpy(s3->access_id,access_id); strcpy(s3->secret_key,secret_key); s3->error[0] = 0; s3->session = NULL; s3->session_count = 0; s3->key_info.nb_name = ne_buffer_create(); s3->key_info.nb_etag = ne_buffer_create(); s3->key_info.nb_storage_class = ne_buffer_create(); s3->key_info.nb_owner_id = ne_buffer_create(); s3->key_info.nb_owner_display_name = ne_buffer_create(); ne_sock_init(); return s3; }
static ne_buffer *acl_body(ne_acl_entry *right, int count) { ne_buffer *body = ne_buffer_create(); int m; ne_buffer_zappend(body, "<?xml version=\"1.0\" encoding=\"utf-8\"?>" EOL "<acl xmlns='DAV:'>" EOL); for (m = 0; m < count; m++) { const char *type; type = (right[m].type == ne_acl_grant ? "grant" : "deny"); ne_buffer_concat(body, "<ace>" EOL "<principal>", NULL); switch (right[m].apply) { case ne_acl_all: ne_buffer_zappend(body, "<all/>" EOL); break; case ne_acl_property: ne_buffer_concat(body, "<property><", right[m].principal, "/></property>" EOL, NULL); break; case ne_acl_href: ne_buffer_concat(body, "<href>", right[m].principal, "</href>" EOL, NULL); break; } ne_buffer_concat(body, "</principal>" EOL "<", type, ">" EOL, NULL); if (right[m].read == 0) ne_buffer_concat(body, "<privilege>" "<read/>" "</privilege>" EOL, NULL); if (right[m].read_acl == 0) ne_buffer_concat(body, "<privilege>" "<read-acl/>" "</privilege>" EOL, NULL); if (right[m].write == 0) ne_buffer_concat(body, "<privilege>" "<write/>" "</privilege>" EOL, NULL); if (right[m].write_acl == 0) ne_buffer_concat(body, "<privilege>" "<write-acl/>" "</privilege>" EOL, NULL); if (right[m].read_cuprivset == 0) ne_buffer_concat(body, "<privilege>" "<read-current-user-privilege-set/>" "</privilege>" EOL, NULL); ne_buffer_concat(body, "</", type, ">" EOL, NULL); ne_buffer_zappend(body, "</ace>" EOL); } ne_buffer_zappend(body, "</acl>" EOL); return body; }
/* Discover all locks on URI */ int ne_lock_discover(ne_session *sess, const char *uri, ne_lock_result callback, void *userdata) { ne_propfind_handler *handler; struct discover_ctx ctx = {0}; int ret; ctx.results = callback; ctx.userdata = userdata; ctx.session = sess; ctx.cdata = ne_buffer_create(); handler = ne_propfind_create(sess, uri, NE_DEPTH_ZERO,"PROPFIND"); ne_propfind_set_private(handler, ld_create, &ctx); ne_xml_push_handler(ne_propfind_get_parser(handler), ld_startelm, ld_cdata, end_element_ldisc, handler); ret = ne_propfind_named(handler, lock_props, discover_results, &ctx); ne_buffer_destroy(ctx.cdata); ne_propfind_destroy(handler); return ret; }
static int simple(void) { ne_buffer *s = ne_buffer_create(); ON(s == NULL); ne_buffer_zappend(s, "abcde"); ONCMP(s->data, "abcde"); ON(ne_buffer_size(s) != 5); ne_buffer_destroy(s); return OK; }
static int buf_concat(void) { ne_buffer *s = ne_buffer_create(); ON(s == NULL); ne_buffer_concat(s, "a", "b", "c", "d", "e", "f", "g", NULL); ONCMP(s->data, "abcdefg"); ON(ne_buffer_size(s) != 7); ne_buffer_destroy(s); return OK; }
int s3_get_bucket(S3 *s3,const char *bucket, const char *prefix,const char *marker,int max_keys,const char *delimiter, const S3KeyInfoCallback *key_info_cb) { ne_request *req; int err, retry; ne_buffer *params; if(!s3) return -1; if(!bucket) return -1; params = ne_buffer_create(); if(prefix) ne_buffer_concat(params,"prefix=",prefix,"/&",NULL); if(marker) ne_buffer_concat(params,"marker=",marker,"&",NULL); if(max_keys >= 0) { char mk[16]; snprintf(mk,16,"%d",max_keys); mk[15] = 0; ne_buffer_concat(params,"max_keys=",max_keys,"&",NULL); } if(delimiter) ne_buffer_concat(params,"delimiter=",delimiter,"&",NULL); s3_begin_session(s3); req = s3_new_request(s3,"GET",bucket,NULL,params->data,NULL); ne_buffer_destroy(params); // send to server do { err = ne_begin_request(req); if(err != NE_OK) err = -EIO; else { if(ne_get_status(req)->code != 200) { s3_handle_error_response(s3,req); err = -EACCES; } else { s3->key_info.key_info_cb = key_info_cb; s3_parse_xml_response(s3, req, s3_xml_key_info_startelm, s3_xml_key_info_cdata, s3_xml_key_info_endelm, &s3->key_info ); } retry = ne_end_request(req); } } while(retry == NE_RETRY); ne_request_destroy(req); s3_end_session(s3); return err; }
static int buf_concat3(void) { ne_buffer *s = ne_buffer_create(); ON(s == NULL); ne_buffer_zappend(s, "foobar"); ne_buffer_concat(s, "norman", NULL); ONCMP(s->data, "foobarnorman"); ON(ne_buffer_size(s) != 12); ne_buffer_destroy(s); return OK; }
char *ne_ssl_readable_dname(const ne_ssl_dname *name) { gnutls_x509_dn_t dn; int ret, rdn = 0, flag = 0; ne_buffer *buf; gnutls_x509_ava_st val; #ifdef HAVE_NEW_DN_API dn = name->dn; #else if (name->subject) ret = gnutls_x509_crt_get_subject(name->cert, &dn); else ret = gnutls_x509_crt_get_issuer(name->cert, &dn); if (ret) return ne_strdup(_("[unprintable]")); #endif /* HAVE_NEW_DN_API */ buf = ne_buffer_create(); /* Find the highest rdn... */ while (gnutls_x509_dn_get_rdn_ava(dn, rdn++, 0, &val) == 0) ; /* ..then iterate back to the first: */ while (--rdn >= 0) { int ava = 0; /* Iterate through all AVAs for multivalued AVAs; better than * ne_openssl can do! */ do { ret = gnutls_x509_dn_get_rdn_ava(dn, rdn, ava, &val); /* If the *only* attribute to append is the common name or * email address, use it; otherwise skip those * attributes. */ if (ret == 0 && val.value.size > 0 && ((!CMPOID(&val, OID_emailAddress) && !CMPOID(&val, OID_commonName)) || (buf->used == 1 && rdn == 0))) { flag = 1; if (buf->used > 1) ne_buffer_append(buf, ", ", 2); append_dirstring(buf, &val.value, val.value_tag); } ava++; } while (ret == 0); } return ne_buffer_finish(buf); }
static int buf_concat2(void) { #define RES "alphabetagammadeltaepsilonetatheta" ne_buffer *s = ne_buffer_create(); ON(s == NULL); ne_buffer_concat(s, "alpha", "beta", "gamma", "delta", "epsilon", "eta", "theta", NULL); ONCMP(s->data, RES); ON(ne_buffer_size(s) != strlen(RES)); ne_buffer_destroy(s); return OK; }
static ne_buffer *set_object_serialise_form(object_query_t *handle) { const char *vname = NULL; assert(NULL != handle); /* Sanity checks */ assert(SET_OBJECT_REQUEST == handle->type); /* Create buffer */ ne_buffer *buff = ne_buffer_create(); /* neon API ref. states that the function always succeeds */ assert(NULL != buff); /* Simple request */ if (1 == object_query_size(handle)) { assert(NULL != handle->head); /* TODO: Simple req. doesn't seem to work vname = vname_nut2mge_xml(handle->head->payld.req.name); */ } if (NULL != vname) { assert(NULL != handle->head); ne_buffer_zappend(buff, "objectName="); ne_buffer_zappend(buff, vname); ne_buffer_zappend(buff, "&objectValue="); ne_buffer_zappend(buff, handle->head->payld.req.value); } /* Multi set request (or empty request) */ else { /* Add request prologue */ ne_buffer_zappend(buff, "--" FORM_POST_BOUNDARY "\r\n"); ne_buffer_zappend(buff, "Content-Disposition: form-data; name=\"file\"; " "filename=\"Configuration.xml\"\r\n"); ne_buffer_zappend(buff, "Content-Type: application/octet-stream\r\n"); ne_buffer_zappend(buff, "\r\n"); /* Serialise all entries */ set_object_serialise_entries(buff, handle->head); /* Add request epilogue */ ne_buffer_zappend(buff, "--" FORM_POST_BOUNDARY "--\r\n"); } return buff; }
/* Return a malloc-allocated human-readable error string describing * GnuTLS verification error bitmask 'status'; return value must be * freed by the caller. */ static char *verify_error_string(unsigned int status) { ne_buffer *buf = ne_buffer_create(); /* sorry, i18n-ers */ if (status & GNUTLS_CERT_INSECURE_ALGORITHM) { ne_buffer_zappend(buf, _("signed using insecure algorithm")); } else { ne_buffer_snprintf(buf, 64, _("unrecognized errors (%u)"), status); } return ne_buffer_finish(buf); }
static int buf_print(void) { ne_buffer *buf = ne_buffer_create(); ne_buffer_czappend(buf, "foo-"); ne_buffer_snprintf(buf, 20, "bar-%s-asda", "norman"); ne_buffer_czappend(buf, "-bloo"); ONN("snprintf return value", ne_buffer_snprintf(buf, 2, "---") != 1); ONCMP(buf->data, "foo-bar-norman-asda-bloo-"); ne_buffer_destroy(buf); return OK; }
static int alter(void) { ne_buffer *s = ne_buffer_create(); char *d; ON(s == NULL); ne_buffer_zappend(s, "abcdefg"); d = s->data; ON(d == NULL); d[2] = '\0'; ne_buffer_altered(s); ONCMP(s->data, "ab"); ON(ne_buffer_size(s) != 2); ne_buffer_zappend(s, "hijkl"); ONCMP(s->data, "abhijkl"); ne_buffer_destroy(s); return OK; }
static object_query_t *set_object_raw(object_query_t *req) { int resp_code; object_query_t *resp = NULL; ne_buffer *req_body = NULL; ne_buffer *resp_body = NULL; assert(NULL != req); /* Sanity check */ assert(SET_OBJECT_REQUEST == req->type); assert(RAW_POST == req->mode); /* Serialise request POST data */ req_body = set_object_serialise_raw(req); /* Send request */ resp_body = ne_buffer_create(); assert(NULL != resp_body); resp_code = send_http_request(session, "POST", "/set_obj.htm", NULL, req_body, resp_body); /* * Repeat in case of 401 - Unauthorised * * Note that this is a WA of NMC sending Connection: close * header in the 401 response, in which case neon closes * connection (quite rightfully). */ if (401 == resp_code) resp_code = send_http_request(session, "POST", "/set_obj.htm", NULL, req_body, resp_body); /* Deserialise response */ if (200 == resp_code) resp = set_object_deserialise_raw(resp_body); /* Cleanup */ if (NULL != req_body) ne_buffer_destroy(req_body); if (NULL != resp_body) ne_buffer_destroy(resp_body); return resp; }
static ne_buffer *set_object_serialise_raw(object_query_t *handle) { assert(NULL != handle); /* Sanity checks */ assert(SET_OBJECT_REQUEST == handle->type); /* Create buffer */ ne_buffer *buff = ne_buffer_create(); /* neon API ref. states that the function always succeeds */ assert(NULL != buff); /* Serialise all entries */ set_object_serialise_entries(buff, handle->head); return buff; }
static int append(void) { ne_buffer *s = ne_buffer_create(); ON(s == NULL); ne_buffer_append(s, "a", 1); ne_buffer_append(s, "b", 1); ne_buffer_append(s, "c", 1); ONCMP(s->data, "abc"); ON(ne_buffer_size(s) != 3); ne_buffer_zappend(s, "hello"); ONCMP(s->data, "abchello"); ne_buffer_czappend(s, "world"); ONCMP(s->data, "abchelloworld"); ON(ne_buffer_size(s) != 13); ne_buffer_destroy(s); return OK; }
int ne_lock_refresh(ne_session *sess, struct ne_lock *lock) { ne_request *req = ne_request_create(sess, "LOCK", lock->uri.path); ne_xml_parser *parser = ne_xml_create(); int ret; struct lock_ctx ctx; memset(&ctx, 0, sizeof ctx); ctx.cdata = ne_buffer_create(); ctx.req = req; ctx.token = lock->token; /* Handle the response and update *lock appropriately. */ ne_xml_push_handler(parser, lk_startelm, lk_cdata, lk_endelm, &ctx); /* For a lock refresh, submitting only this lock token must be * sufficient. */ ne_print_request_header(req, "If", "(<%s>)", lock->token); add_timeout_header(req, lock->timeout); ret = ne_xml_dispatch_request(req, parser); if (ret == NE_OK) { if (ne_get_status(req)->klass != 2) { ret = NE_ERROR; /* and use default session error */ } else if (ne_xml_failed(parser)) { ret = NE_ERROR; ne_set_error(sess, "%s", ne_xml_get_error(parser)); } else if (!ctx.found) { ne_set_error(sess, _("No activelock for <%s> returned in " "LOCK refresh response"), lock->token); ret = NE_ERROR; } else /* success! */ { /* update timeout for passed-in lock structure. */ lock->timeout = ctx.active.timeout; } } ne_lock_free(&ctx.active); ne_buffer_destroy(ctx.cdata); ne_request_destroy(req); ne_xml_destroy(parser); return ret; }
char *ne_ssl_readable_dname(const ne_ssl_dname *name) { ne_buffer *buf = ne_buffer_create(); int ret, idx = 0; do { char oid[32] = {0}; size_t oidlen = sizeof oid; ret = name->subject ? gnutls_x509_crt_get_dn_oid(name->cert, idx, oid, &oidlen) : gnutls_x509_crt_get_issuer_dn_oid(name->cert, idx, oid, &oidlen); if (ret == 0) { append_rdn(buf, name->cert, name->subject, oid); idx++; } } while (ret != GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE); return ne_buffer_finish(buf); }
static int qappend(void) { static const struct { const char *in; size_t inlen; const char *out; } ts[] = { { "", 0, "" }, { "a", 1, "a" }, { "b", 2, "b\\x00" }, { "alpha\0alpha", 11, "alpha\\x00alpha" }, { "a\tb", 3, "a\\x09b" }, { NULL } }; unsigned n; for (n = 0; ts[n].in; n++) { ne_buffer *buf = ne_buffer_create(); char *s; const unsigned char *in = (const unsigned char *)ts[n].in; ne_buffer_qappend(buf, in, ts[n].inlen); ONCMP(buf->data, ts[n].out); ONV(strlen(buf->data) + 1 != buf->used, ("bad buffer length for '%s': %" NE_FMT_SIZE_T, ts[n].out, buf->used)); s = ne_strnqdup(in, ts[n].inlen); ONCMP(s, ts[n].out); ne_free(s); ne_buffer_destroy(buf); } return OK; }
char *ne_uri_unparse(const ne_uri *uri) { ne_buffer *buf = ne_buffer_create(); if (uri->scheme) { ne_buffer_concat(buf, uri->scheme, ":", NULL); } if (uri->host) { ne_buffer_czappend(buf, "//"); if (uri->userinfo) { ne_buffer_concat(buf, uri->userinfo, "@", NULL); } ne_buffer_zappend(buf, uri->host); if (uri->port > 0 && (!uri->scheme || ne_uri_defaultport(uri->scheme) != uri->port)) { char str[20]; ne_snprintf(str, 20, ":%d", uri->port); ne_buffer_zappend(buf, str); } } ne_buffer_zappend(buf, uri->path); if (uri->query) { ne_buffer_concat(buf, "?", uri->query, NULL); } if (uri->fragment) { ne_buffer_concat(buf, "#", uri->fragment, NULL); } return ne_buffer_finish(buf); }
char *ne_ssl_readable_dname(const ne_ssl_dname *name) { int n, flag = 0; ne_buffer *dump = ne_buffer_create(); const ASN1_OBJECT * const cname = OBJ_nid2obj(NID_commonName), * const email = OBJ_nid2obj(NID_pkcs9_emailAddress); for (n = X509_NAME_entry_count(name->dn); n > 0; n--) { X509_NAME_ENTRY *ent = X509_NAME_get_entry(name->dn, n-1); /* Skip commonName or emailAddress except if there is no other * attribute in dname. */ if ((OBJ_cmp(ent->object, cname) && OBJ_cmp(ent->object, email)) || (!flag && n == 1)) { if (flag++) ne_buffer_append(dump, ", ", 2); if (append_dirstring(dump, ent->value)) ne_buffer_czappend(dump, "???"); } } return ne_buffer_finish(dump); }
/* Return Digest authentication credentials header value for the given * session. */ static char *request_digest(auth_session *sess, struct auth_request *req) { struct ne_md5_ctx a2, rdig; unsigned char a2_md5[16], rdig_md5[16]; char a2_md5_ascii[33], rdig_md5_ascii[33]; char nc_value[9] = {0}; const char *qop_value = "auth"; /* qop-value */ ne_buffer *ret; /* Increase the nonce-count */ if (sess->qop != auth_qop_none) { sess->nonce_count++; ne_snprintf(nc_value, 9, "%08x", sess->nonce_count); NE_DEBUG(NE_DBG_HTTPAUTH, "Nonce count is %u, nc is [%s]\n", sess->nonce_count, nc_value); } /* Calculate H(A2). */ ne_md5_init_ctx(&a2); ne_md5_process_bytes(req->method, strlen(req->method), &a2); ne_md5_process_bytes(":", 1, &a2); ne_md5_process_bytes(req->uri, strlen(req->uri), &a2); ne_md5_finish_ctx(&a2, a2_md5); ne_md5_to_ascii(a2_md5, a2_md5_ascii); NE_DEBUG(NE_DBG_HTTPAUTH, "H(A2): %s\n", a2_md5_ascii); NE_DEBUG(NE_DBG_HTTPAUTH, "Calculating Request-Digest.\n"); /* Now, calculation of the Request-Digest. * The first section is the regardless of qop value * H(A1) ":" unq(nonce-value) ":" */ ne_md5_init_ctx(&rdig); /* Use the calculated H(A1) */ ne_md5_process_bytes(sess->h_a1, 32, &rdig); ne_md5_process_bytes(":", 1, &rdig); ne_md5_process_bytes(sess->nonce, strlen(sess->nonce), &rdig); ne_md5_process_bytes(":", 1, &rdig); if (sess->qop != auth_qop_none) { /* Add on: * nc-value ":" unq(cnonce-value) ":" unq(qop-value) ":" */ NE_DEBUG(NE_DBG_HTTPAUTH, "Have qop directive, digesting: [%s:%s:%s]\n", nc_value, sess->cnonce, qop_value); ne_md5_process_bytes(nc_value, 8, &rdig); ne_md5_process_bytes(":", 1, &rdig); ne_md5_process_bytes(sess->cnonce, strlen(sess->cnonce), &rdig); ne_md5_process_bytes(":", 1, &rdig); /* Store a copy of this structure (see note below) */ sess->stored_rdig = rdig; ne_md5_process_bytes(qop_value, strlen(qop_value), &rdig); ne_md5_process_bytes(":", 1, &rdig); } else { /* Store a copy of this structure... we do this because the * calculation of the rspauth= field in the Auth-Info header * is the same as this digest, up to this point. */ sess->stored_rdig = rdig; } /* And finally, H(A2) */ ne_md5_process_bytes(a2_md5_ascii, 32, &rdig); ne_md5_finish_ctx(&rdig, rdig_md5); ne_md5_to_ascii(rdig_md5, rdig_md5_ascii); ret = ne_buffer_create(); ne_buffer_concat(ret, "Digest username=\"", sess->username, "\", " "realm=\"", sess->realm, "\", " "nonce=\"", sess->nonce, "\", " "uri=\"", req->uri, "\", " "response=\"", rdig_md5_ascii, "\", " "algorithm=\"", sess->alg == auth_alg_md5 ? "MD5" : "MD5-sess", "\"", NULL); if (sess->opaque != NULL) { ne_buffer_concat(ret, ", opaque=\"", sess->opaque, "\"", NULL); } if (sess->qop != auth_qop_none) { /* Add in cnonce and nc-value fields */ ne_buffer_concat(ret, ", cnonce=\"", sess->cnonce, "\", " "nc=", nc_value, ", " "qop=\"", qop_value, "\"", NULL); } ne_buffer_zappend(ret, "\r\n"); NE_DEBUG(NE_DBG_HTTPAUTH, "Digest request header is %s\n", ret->data); return ne_buffer_finish(ret); }
/* Continue a GSS-API Negotiate exchange, using input TOKEN if * non-NULL. Returns non-zero on error. */ static int continue_negotiate(auth_session *sess, const char *token) { unsigned int major, minor; gss_buffer_desc input = GSS_C_EMPTY_BUFFER; gss_buffer_desc output = GSS_C_EMPTY_BUFFER; unsigned char *bintoken = NULL; int ret; if (token) { input.length = ne_unbase64(token, &bintoken); if (input.length == 0) { NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Invalid input [%s].\n", token); return -1; } input.value = bintoken; NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Continuation token [%s]\n", token); } else if (sess->gssctx != GSS_C_NO_CONTEXT) { NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Reset incomplete context.\n"); gss_delete_sec_context(&minor, &sess->gssctx, GSS_C_NO_BUFFER); } major = gss_init_sec_context(&minor, GSS_C_NO_CREDENTIAL, &sess->gssctx, sess->gssname, sess->gssmech, GSS_C_MUTUAL_FLAG, GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, &input, &sess->gssmech, &output, NULL, NULL); /* done with the input token. */ if (bintoken) ne_free(bintoken); if (GSS_ERROR(major)) { ne_buffer *err = ne_buffer_create(); int flag = 0; make_gss_error(err, &flag, major, GSS_C_GSS_CODE); make_gss_error(err, &flag, minor, GSS_C_MECH_CODE); NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Error: %s\n", err->data); ne_set_error(sess->sess, _("GSSAPI authentication error (%s)"), err->data); ne_buffer_destroy(err); return -1; } if (major == GSS_S_CONTINUE_NEEDED || major == GSS_S_COMPLETE) { NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: init_sec_context OK. (major=%d)\n", major); ret = 0; } else { NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Init failure %d.\n", major); ret = -1; } if (major != GSS_S_CONTINUE_NEEDED) { /* context no longer needed: destroy it */ gss_delete_sec_context(&minor, &sess->gssctx, GSS_C_NO_BUFFER); } if (output.length) { sess->gssapi_token = ne_base64(output.value, output.length); NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: Output token: [%s]\n", sess->gssapi_token); gss_release_buffer(&minor, &output); } else { NE_DEBUG(NE_DBG_HTTPAUTH, "gssapi: No output token.\n"); } return ret; }
static ne_request *s3_new_request(const S3 *s3,const char *method,const char *bucket,const char *key,const char *params,const char *content_type) { ne_buffer *date, *signing_string, *request_str; ne_request *req; char *sig, *p; time_t t; if(!s3) return NULL; if(!method) return NULL; if(!bucket) return NULL; if(!s3->session) return NULL; // create some string buffers date = ne_buffer_create(); signing_string = ne_buffer_create(); request_str = ne_buffer_create(); // get the time t = time(NULL); ne_buffer_zappend(date,asctime(gmtime(&t))); if(date->data[date->used - 2] == '\n') date->data[date->used - 2] = 0; ne_buffer_altered(date); // create request if(key) ne_buffer_concat(request_str,"/",bucket,"/",key,NULL); else ne_buffer_concat(request_str,"/",bucket,NULL); if(params && params[0] != 0) { ne_buffer_zappend(request_str,"?"); ne_buffer_zappend(request_str,params); } req = ne_request_create(s3->session,method,request_str->data); // Add date header ne_add_request_header(req,"Date",date->data); // Add content-type header if(content_type) ne_add_request_header(req,"Content-Type",content_type); else content_type = ""; // construct signing string p = strrchr(request_str->data,'?'); if(p) { *p = 0; ne_buffer_altered(request_str); } ne_buffer_concat(signing_string,method,"\n\n",content_type,"\n",date->data,"\n",request_str->data,NULL); // sign the string sig = s3_sign_string(s3,signing_string->data); // construct signed header ne_print_request_header(req,"Authorization","AWS %s:%s",s3->access_id,sig); ne_buffer_destroy(date); ne_buffer_destroy(signing_string); ne_buffer_destroy(request_str); free(sig); return req; }
static ne_buffer *acl_body(const ne_acl_entry *right, int count) { ne_buffer *body = ne_buffer_create(); int m; ne_buffer_zappend(body, "<?xml version=\"1.0\" encoding=\"utf-8\"?>" EOL "<acl xmlns='DAV:'>" EOL); for (m = 0; m < count; m++) { const char *type; type = (right[m].type == ne_acl_grant ? "grant" : "deny"); ne_buffer_concat(body, "<ace>" EOL "<principal>", NULL); switch (right[m].target) { case ne_acl_all: ne_buffer_czappend(body, "<all/>" EOL); break; case ne_acl_authenticated: ne_buffer_czappend(body, "<authenticated/>" EOL); break; case ne_acl_unauthenticated: ne_buffer_czappend(body, "<unauthenticated/>" EOL); break; case ne_acl_self: ne_buffer_czappend(body, "<self/>" EOL); break; case ne_acl_property: ne_buffer_concat(body, "<property><", right[m].tname, "/></property>" EOL, NULL); break; case ne_acl_href: ne_buffer_concat(body, "<href>", right[m].tname, "</href>" EOL, NULL); break; } ne_buffer_concat(body, "</principal>" EOL "<", type, ">" EOL, NULL); if ((right[m].privileges & NE_ACL_READ) == NE_ACL_READ) ne_buffer_concat(body, "<privilege>" "<read/>" "</privilege>" EOL, NULL); if ((right[m].privileges & NE_ACL_WRITE) == NE_ACL_WRITE) ne_buffer_concat(body, "<privilege>" "<write/>" "</privilege>" EOL, NULL); if ((right[m].privileges & NE_ACL_WRITE_PROPERTIES) == NE_ACL_WRITE_PROPERTIES) ne_buffer_concat(body, "<privilege>" "<write-properties/>" "</privilege>" EOL, NULL); if ((right[m].privileges & NE_ACL_WRITE_CONTENT) == NE_ACL_WRITE_CONTENT) ne_buffer_concat(body, "<privilege>" "<write-content/>" "</privilege>" EOL, NULL); if ((right[m].privileges & NE_ACL_UNLOCK) == NE_ACL_UNLOCK) ne_buffer_concat(body, "<privilege>" "<unlock/>" "</privilege>" EOL, NULL); if ((right[m].privileges & NE_ACL_READ_ACL) == NE_ACL_READ_ACL) ne_buffer_concat(body, "<privilege>" "<read-acl/>" "</privilege>" EOL, NULL); if ((right[m].privileges & NE_ACL_READ_CUPRIVSET) == NE_ACL_READ_CUPRIVSET) ne_buffer_concat(body, "<privilege>" "<read-current-user-privileges-set/>" "</privilege>" EOL, NULL); if ((right[m].privileges & NE_ACL_WRITE_ACL) == NE_ACL_WRITE_ACL) ne_buffer_concat(body, "<privilege>" "<write-acl/>" "</privilege>" EOL, NULL); if ((right[m].privileges & NE_ACL_BIND) == NE_ACL_BIND) ne_buffer_concat(body, "<privilege>" "<bind/>" "</privilege>" EOL, NULL); if ((right[m].privileges & NE_ACL_UNBIND) == NE_ACL_UNBIND) ne_buffer_concat(body, "<privilege>" "<unbind/>" "</privilege>" EOL, NULL); if ((right[m].privileges & NE_ACL_ALL) == NE_ACL_ALL) ne_buffer_concat(body, "<privilege>" "<all/>" "</privilege>" EOL, NULL); ne_buffer_concat(body, "</", type, ">" EOL, NULL); ne_buffer_czappend(body, "</ace>" EOL); } ne_buffer_czappend(body, "</acl>" EOL); return body; }
int ne_lock(ne_session *sess, struct ne_lock *lock) { ne_request *req = ne_request_create(sess, "LOCK", lock->uri.path); ne_buffer *body = ne_buffer_create(); ne_xml_parser *parser = ne_xml_create(); int ret, parse_failed; struct lock_ctx ctx; memset(&ctx, 0, sizeof ctx); ctx.cdata = ne_buffer_create(); ctx.req = req; ne_xml_push_handler(parser, lk_startelm, lk_cdata, lk_endelm, &ctx); /* Create the body */ ne_buffer_concat(body, "<?xml version=\"1.0\" encoding=\"utf-8\"?>" EOL "<lockinfo xmlns='DAV:'>" EOL " <lockscope>", lock->scope==ne_lockscope_exclusive? "<exclusive/>":"<shared/>", "</lockscope>" EOL "<locktype><write/></locktype>", NULL); if (lock->owner) { ne_buffer_concat(body, "<owner>", lock->owner, "</owner>" EOL, NULL); } ne_buffer_zappend(body, "</lockinfo>" EOL); ne_set_request_body_buffer(req, body->data, ne_buffer_size(body)); /* ne_add_request_header(req, "Content-Type", NE_XML_MEDIA_TYPE); */ /* Just to test whether sever accepts both text/xml and application/xml */ ne_add_request_header(req, "Content-Type", "text/xml"); ne_add_depth_header(req, lock->depth); add_timeout_header(req, lock->timeout); /* TODO: * By 2518, we need this only if we are creating a lock-null resource. * Since we don't KNOW whether the lock we're given is a lock-null * or not, we cover our bases. */ ne_lock_using_parent(req, lock->uri.path); /* This one is clearer from 2518 sec 8.10.4. */ ne_lock_using_resource(req, lock->uri.path, lock->depth); ret = ne_xml_dispatch_request(req, parser); ne_buffer_destroy(body); ne_buffer_destroy(ctx.cdata); parse_failed = ne_xml_failed(parser); if (ret == NE_OK && ne_get_status(req)->klass == 2) { if (ctx.token == NULL) { ret = NE_ERROR; ne_set_error(sess, _("No Lock-Token header given")); } else if (parse_failed) { ret = NE_ERROR; ne_set_error(sess, "%s", ne_xml_get_error(parser)); } else if (ne_get_status(req)->code == 207) { ret = NE_ERROR; /* TODO: set the error string appropriately */ } else if (ctx.found) { /* it worked: copy over real lock details if given. */ if (lock->token) ne_free(lock->token); lock->token = ctx.token; ctx.token = NULL; if (ctx.active.timeout != NE_TIMEOUT_INVALID) lock->timeout = ctx.active.timeout; lock->scope = ctx.active.scope; lock->type = ctx.active.type; if (ctx.active.depth >= 0) lock->depth = ctx.active.depth; if (ctx.active.owner) { if (lock->owner) ne_free(lock->owner); lock->owner = ctx.active.owner; ctx.active.owner = NULL; } } else { ret = NE_ERROR; ne_set_error(sess, _("Response missing activelock for %s"), ctx.token); } } else if (ret == NE_OK /* && status != 2xx */) { ret = NE_ERROR; } ne_lock_free(&ctx.active); if (ctx.token) ne_free(ctx.token); ne_request_destroy(req); ne_xml_destroy(parser); return ret; }