1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * S3 Put Object via Secure Streams minimal siv4 example
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Written in 2010-2020 by Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker * Amit Pachore <[email protected]>
6*1c60b9acSAndroid Build Coastguard Worker * [email protected]
7*1c60b9acSAndroid Build Coastguard Worker *
8*1c60b9acSAndroid Build Coastguard Worker * This file is made available under the Creative Commons CC0 1.0
9*1c60b9acSAndroid Build Coastguard Worker * Universal Public Domain Dedication.
10*1c60b9acSAndroid Build Coastguard Worker */
11*1c60b9acSAndroid Build Coastguard Worker
12*1c60b9acSAndroid Build Coastguard Worker #include <libwebsockets.h>
13*1c60b9acSAndroid Build Coastguard Worker #include <assert.h>
14*1c60b9acSAndroid Build Coastguard Worker #include "ss-s3-put.h"
15*1c60b9acSAndroid Build Coastguard Worker
16*1c60b9acSAndroid Build Coastguard Worker extern int interrupted, bad;
17*1c60b9acSAndroid Build Coastguard Worker
18*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_s3_rx(void * userobj,const uint8_t * buf,size_t len,int flags)19*1c60b9acSAndroid Build Coastguard Worker ss_s3_rx(void *userobj, const uint8_t *buf, size_t len, int flags)
20*1c60b9acSAndroid Build Coastguard Worker {
21*1c60b9acSAndroid Build Coastguard Worker // ss_s3_put_t *m = (ss_s3_put_t *)userobj;
22*1c60b9acSAndroid Build Coastguard Worker
23*1c60b9acSAndroid Build Coastguard Worker if (flags & LWSSS_FLAG_EOM) {
24*1c60b9acSAndroid Build Coastguard Worker bad = 0;
25*1c60b9acSAndroid Build Coastguard Worker interrupted = 1; /* this example wants to exit after rx */
26*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
27*1c60b9acSAndroid Build Coastguard Worker }
28*1c60b9acSAndroid Build Coastguard Worker
29*1c60b9acSAndroid Build Coastguard Worker lwsl_user("%s: len %d, flags: %d\n", __func__, (int)len, flags);
30*1c60b9acSAndroid Build Coastguard Worker lwsl_hexdump_err(buf, len);
31*1c60b9acSAndroid Build Coastguard Worker
32*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
33*1c60b9acSAndroid Build Coastguard Worker }
34*1c60b9acSAndroid Build Coastguard Worker
35*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_s3_tx(void * userobj,lws_ss_tx_ordinal_t ord,uint8_t * buf,size_t * len,int * flags)36*1c60b9acSAndroid Build Coastguard Worker ss_s3_tx(void *userobj, lws_ss_tx_ordinal_t ord, uint8_t *buf, size_t *len,
37*1c60b9acSAndroid Build Coastguard Worker int *flags)
38*1c60b9acSAndroid Build Coastguard Worker {
39*1c60b9acSAndroid Build Coastguard Worker ss_s3_put_t *m = (ss_s3_put_t *)userobj;
40*1c60b9acSAndroid Build Coastguard Worker
41*1c60b9acSAndroid Build Coastguard Worker if (!m->pos)
42*1c60b9acSAndroid Build Coastguard Worker *flags |= LWSSS_FLAG_SOM;
43*1c60b9acSAndroid Build Coastguard Worker
44*1c60b9acSAndroid Build Coastguard Worker lwsl_user("%s: Send... total: %ld, pos: %ld\n", __func__,
45*1c60b9acSAndroid Build Coastguard Worker (long)m->total, (long)m->pos);
46*1c60b9acSAndroid Build Coastguard Worker
47*1c60b9acSAndroid Build Coastguard Worker if (*len > m->total - m->pos)
48*1c60b9acSAndroid Build Coastguard Worker *len = m->total - m->pos;
49*1c60b9acSAndroid Build Coastguard Worker
50*1c60b9acSAndroid Build Coastguard Worker if (!*len)
51*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_TX_DONT_SEND;
52*1c60b9acSAndroid Build Coastguard Worker
53*1c60b9acSAndroid Build Coastguard Worker memcpy(buf, m->buf + m->pos, *len);
54*1c60b9acSAndroid Build Coastguard Worker m->pos += *len;
55*1c60b9acSAndroid Build Coastguard Worker
56*1c60b9acSAndroid Build Coastguard Worker if (m->pos == m->total) {
57*1c60b9acSAndroid Build Coastguard Worker *flags |= LWSSS_FLAG_EOM;
58*1c60b9acSAndroid Build Coastguard Worker // m->pos = 0; /* we only want to send once */
59*1c60b9acSAndroid Build Coastguard Worker } else
60*1c60b9acSAndroid Build Coastguard Worker return lws_ss_request_tx(m->ss);
61*1c60b9acSAndroid Build Coastguard Worker
62*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_OK;
63*1c60b9acSAndroid Build Coastguard Worker }
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Worker static const char *awsService = "s3",
66*1c60b9acSAndroid Build Coastguard Worker *awsRegion = "us-west-2",
67*1c60b9acSAndroid Build Coastguard Worker *s3bucketName = "sstest2020",
68*1c60b9acSAndroid Build Coastguard Worker #if 1
69*1c60b9acSAndroid Build Coastguard Worker *s3ObjName = "SSs3upload2.txt";
70*1c60b9acSAndroid Build Coastguard Worker #else
71*1c60b9acSAndroid Build Coastguard Worker /* test huge string sigv4 hashing works */
72*1c60b9acSAndroid Build Coastguard Worker *s3ObjName = "SSs3uploadaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa2.txt";
73*1c60b9acSAndroid Build Coastguard Worker #endif
74*1c60b9acSAndroid Build Coastguard Worker static char timestamp[32], payload_hash[65];
75*1c60b9acSAndroid Build Coastguard Worker static uint8_t jpl[1 * 1024];
76*1c60b9acSAndroid Build Coastguard Worker
77*1c60b9acSAndroid Build Coastguard Worker
78*1c60b9acSAndroid Build Coastguard Worker static void
create_payload(uint8_t * buf,size_t s)79*1c60b9acSAndroid Build Coastguard Worker create_payload(uint8_t *buf, size_t s)
80*1c60b9acSAndroid Build Coastguard Worker {
81*1c60b9acSAndroid Build Coastguard Worker int i;
82*1c60b9acSAndroid Build Coastguard Worker
83*1c60b9acSAndroid Build Coastguard Worker for (i = 0; i < (int)s; i++)
84*1c60b9acSAndroid Build Coastguard Worker buf[i] = (uint8_t)('a' + i % 16);
85*1c60b9acSAndroid Build Coastguard Worker }
86*1c60b9acSAndroid Build Coastguard Worker
set_time(char * t)87*1c60b9acSAndroid Build Coastguard Worker static void set_time(char *t)
88*1c60b9acSAndroid Build Coastguard Worker {
89*1c60b9acSAndroid Build Coastguard Worker /*20150830T123600Z*/
90*1c60b9acSAndroid Build Coastguard Worker time_t ti = time(NULL);
91*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_HAVE_GMTIME_R)
92*1c60b9acSAndroid Build Coastguard Worker struct tm tmp;
93*1c60b9acSAndroid Build Coastguard Worker struct tm *tm = gmtime_r(&ti, &tmp);
94*1c60b9acSAndroid Build Coastguard Worker #else
95*1c60b9acSAndroid Build Coastguard Worker struct tm *tm = gmtime(&ti);
96*1c60b9acSAndroid Build Coastguard Worker #endif
97*1c60b9acSAndroid Build Coastguard Worker assert(tm);
98*1c60b9acSAndroid Build Coastguard Worker strftime(t, 20, "%Y%m%dT%H%M%SZ", tm);
99*1c60b9acSAndroid Build Coastguard Worker }
100*1c60b9acSAndroid Build Coastguard Worker
bin2hex(uint8_t * in,size_t len,char * out)101*1c60b9acSAndroid Build Coastguard Worker static void bin2hex(uint8_t *in, size_t len, char *out)
102*1c60b9acSAndroid Build Coastguard Worker {
103*1c60b9acSAndroid Build Coastguard Worker static const char *hex = "0123456789abcdef";
104*1c60b9acSAndroid Build Coastguard Worker size_t n;
105*1c60b9acSAndroid Build Coastguard Worker
106*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < len; n++) {
107*1c60b9acSAndroid Build Coastguard Worker *out++ = hex[(in[n] >> 4) & 0xf];
108*1c60b9acSAndroid Build Coastguard Worker *out++ = hex[in[n] & 15];
109*1c60b9acSAndroid Build Coastguard Worker }
110*1c60b9acSAndroid Build Coastguard Worker *out = '\0';
111*1c60b9acSAndroid Build Coastguard Worker }
112*1c60b9acSAndroid Build Coastguard Worker
sigv4_sha256hash_payload(uint8_t * payload,size_t len,char * hash)113*1c60b9acSAndroid Build Coastguard Worker static void sigv4_sha256hash_payload(uint8_t *payload, size_t len, char *hash)
114*1c60b9acSAndroid Build Coastguard Worker {
115*1c60b9acSAndroid Build Coastguard Worker struct lws_genhash_ctx hash_ctx;
116*1c60b9acSAndroid Build Coastguard Worker uint8_t hash_bin[32];
117*1c60b9acSAndroid Build Coastguard Worker
118*1c60b9acSAndroid Build Coastguard Worker if (lws_genhash_init(&hash_ctx, LWS_GENHASH_TYPE_SHA256) ||
119*1c60b9acSAndroid Build Coastguard Worker /*
120*1c60b9acSAndroid Build Coastguard Worker * If there is no payload, you must provide the hash of an
121*1c60b9acSAndroid Build Coastguard Worker * empty string...
122*1c60b9acSAndroid Build Coastguard Worker */
123*1c60b9acSAndroid Build Coastguard Worker lws_genhash_update(&hash_ctx,
124*1c60b9acSAndroid Build Coastguard Worker payload ? (void *)payload : (void *)"",
125*1c60b9acSAndroid Build Coastguard Worker payload ? len : 0u) ||
126*1c60b9acSAndroid Build Coastguard Worker lws_genhash_destroy(&hash_ctx, hash_bin))
127*1c60b9acSAndroid Build Coastguard Worker {
128*1c60b9acSAndroid Build Coastguard Worker
129*1c60b9acSAndroid Build Coastguard Worker lws_genhash_destroy(&hash_ctx, NULL);
130*1c60b9acSAndroid Build Coastguard Worker lwsl_err("%s lws_genhash failed\n", __func__);
131*1c60b9acSAndroid Build Coastguard Worker
132*1c60b9acSAndroid Build Coastguard Worker return;
133*1c60b9acSAndroid Build Coastguard Worker }
134*1c60b9acSAndroid Build Coastguard Worker
135*1c60b9acSAndroid Build Coastguard Worker bin2hex(hash_bin, 32, hash);
136*1c60b9acSAndroid Build Coastguard Worker }
137*1c60b9acSAndroid Build Coastguard Worker
138*1c60b9acSAndroid Build Coastguard Worker static lws_ss_state_return_t
ss_s3_state(void * userobj,void * sh,lws_ss_constate_t state,lws_ss_tx_ordinal_t ack)139*1c60b9acSAndroid Build Coastguard Worker ss_s3_state(void *userobj, void *sh, lws_ss_constate_t state,
140*1c60b9acSAndroid Build Coastguard Worker lws_ss_tx_ordinal_t ack)
141*1c60b9acSAndroid Build Coastguard Worker {
142*1c60b9acSAndroid Build Coastguard Worker ss_s3_put_t *m = (ss_s3_put_t *)userobj;
143*1c60b9acSAndroid Build Coastguard Worker
144*1c60b9acSAndroid Build Coastguard Worker lwsl_user("%s: %s %s, ord 0x%x\n", __func__, lws_ss_tag(m->ss),
145*1c60b9acSAndroid Build Coastguard Worker lws_ss_state_name((int)state), (unsigned int)ack);
146*1c60b9acSAndroid Build Coastguard Worker
147*1c60b9acSAndroid Build Coastguard Worker switch (state) {
148*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_CREATING:
149*1c60b9acSAndroid Build Coastguard Worker create_payload(jpl, sizeof(jpl));
150*1c60b9acSAndroid Build Coastguard Worker m->buf = (uint8_t *)jpl;
151*1c60b9acSAndroid Build Coastguard Worker m->total = sizeof(jpl);
152*1c60b9acSAndroid Build Coastguard Worker
153*1c60b9acSAndroid Build Coastguard Worker sigv4_sha256hash_payload(m->buf, m->total, payload_hash);
154*1c60b9acSAndroid Build Coastguard Worker memset(timestamp, 0, sizeof(timestamp));
155*1c60b9acSAndroid Build Coastguard Worker set_time(timestamp);
156*1c60b9acSAndroid Build Coastguard Worker
157*1c60b9acSAndroid Build Coastguard Worker if (lws_ss_set_metadata(m->ss, "s3bucket",
158*1c60b9acSAndroid Build Coastguard Worker s3bucketName, strlen(s3bucketName)) ||
159*1c60b9acSAndroid Build Coastguard Worker lws_ss_set_metadata(m->ss, "s3Obj",
160*1c60b9acSAndroid Build Coastguard Worker s3ObjName, strlen(s3ObjName)) ||
161*1c60b9acSAndroid Build Coastguard Worker lws_ss_set_metadata(m->ss, "ctype",
162*1c60b9acSAndroid Build Coastguard Worker "text/plain", strlen("text/plain")) ||
163*1c60b9acSAndroid Build Coastguard Worker lws_ss_set_metadata(m->ss, "region",
164*1c60b9acSAndroid Build Coastguard Worker awsRegion, strlen(awsRegion)) ||
165*1c60b9acSAndroid Build Coastguard Worker lws_ss_set_metadata(m->ss, "service",
166*1c60b9acSAndroid Build Coastguard Worker awsService, strlen(awsService)) ||
167*1c60b9acSAndroid Build Coastguard Worker lws_ss_set_metadata(m->ss, "xacl",
168*1c60b9acSAndroid Build Coastguard Worker "bucket-owner-full-control",
169*1c60b9acSAndroid Build Coastguard Worker strlen("bucket-owner-full-control")) ||
170*1c60b9acSAndroid Build Coastguard Worker lws_ss_set_metadata(m->ss, "xcsha256",
171*1c60b9acSAndroid Build Coastguard Worker payload_hash, strlen(payload_hash)) ||
172*1c60b9acSAndroid Build Coastguard Worker lws_ss_set_metadata(m->ss, "xdate",
173*1c60b9acSAndroid Build Coastguard Worker timestamp, strlen(timestamp)))
174*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
175*1c60b9acSAndroid Build Coastguard Worker
176*1c60b9acSAndroid Build Coastguard Worker return lws_ss_request_tx_len(m->ss, m->total);
177*1c60b9acSAndroid Build Coastguard Worker
178*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_CONNECTED:
179*1c60b9acSAndroid Build Coastguard Worker return lws_ss_request_tx(m->ss);
180*1c60b9acSAndroid Build Coastguard Worker
181*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_DISCONNECTED:
182*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
183*1c60b9acSAndroid Build Coastguard Worker
184*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_ALL_RETRIES_FAILED:
185*1c60b9acSAndroid Build Coastguard Worker /* if we're out of retries, we want to close the app and FAIL */
186*1c60b9acSAndroid Build Coastguard Worker bad = 1;
187*1c60b9acSAndroid Build Coastguard Worker return LWSSSSRET_DESTROY_ME;
188*1c60b9acSAndroid Build Coastguard Worker
189*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_QOS_ACK_REMOTE:
190*1c60b9acSAndroid Build Coastguard Worker bad = 0;
191*1c60b9acSAndroid Build Coastguard Worker break;
192*1c60b9acSAndroid Build Coastguard Worker
193*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_QOS_NACK_REMOTE:
194*1c60b9acSAndroid Build Coastguard Worker bad = 1;
195*1c60b9acSAndroid Build Coastguard Worker break;
196*1c60b9acSAndroid Build Coastguard Worker
197*1c60b9acSAndroid Build Coastguard Worker case LWSSSCS_DESTROYING:
198*1c60b9acSAndroid Build Coastguard Worker interrupted = 1;
199*1c60b9acSAndroid Build Coastguard Worker break;
200*1c60b9acSAndroid Build Coastguard Worker
201*1c60b9acSAndroid Build Coastguard Worker default:
202*1c60b9acSAndroid Build Coastguard Worker break;
203*1c60b9acSAndroid Build Coastguard Worker }
204*1c60b9acSAndroid Build Coastguard Worker
205*1c60b9acSAndroid Build Coastguard Worker return 0;
206*1c60b9acSAndroid Build Coastguard Worker }
207*1c60b9acSAndroid Build Coastguard Worker
208*1c60b9acSAndroid Build Coastguard Worker const lws_ss_info_t s3_ssi = {
209*1c60b9acSAndroid Build Coastguard Worker .handle_offset = offsetof(ss_s3_put_t, ss),
210*1c60b9acSAndroid Build Coastguard Worker .opaque_user_data_offset = offsetof(ss_s3_put_t, opaque_data),
211*1c60b9acSAndroid Build Coastguard Worker .rx = ss_s3_rx,
212*1c60b9acSAndroid Build Coastguard Worker .tx = ss_s3_tx,
213*1c60b9acSAndroid Build Coastguard Worker .state = ss_s3_state,
214*1c60b9acSAndroid Build Coastguard Worker .user_alloc = sizeof(ss_s3_put_t),
215*1c60b9acSAndroid Build Coastguard Worker .streamtype = "s3PutObj"
216*1c60b9acSAndroid Build Coastguard Worker };
217