Statistics
| Branch: | Tag: | Revision:

one / src / common / NebulaUtil.cc @ 202b47e9

History | View | Annotate | Download (13.5 KB)

1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2016, OpenNebula Project, OpenNebula Systems                */
3
/*                                                                            */
4
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
5
/* not use this file except in compliance with the License. You may obtain    */
6
/* a copy of the License at                                                   */
7
/*                                                                            */
8
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
9
/*                                                                            */
10
/* Unless required by applicable law or agreed to in writing, software        */
11
/* distributed under the License is distributed on an "AS IS" BASIS,          */
12
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
13
/* See the License for the specific language governing permissions and        */
14
/* limitations under the License.                                             */
15
/* -------------------------------------------------------------------------- */
16

    
17
#include "NebulaUtil.h"
18

    
19
#include <openssl/sha.h>
20
#include <openssl/hmac.h>
21
#include <openssl/evp.h>
22
#include <openssl/bio.h>
23
#include <openssl/buffer.h>
24
#include <openssl/aes.h>
25

    
26
#include <zlib.h>
27

    
28
#include <string>
29
#include <sstream>
30
#include <cstring>
31
#include <iomanip>
32
#include <algorithm>
33
#include <math.h>
34
#include <sys/types.h>
35
#include <regex.h>
36

    
37
using namespace std;
38

    
39
string& one_util::toupper(string& st)
40
{
41
    transform(st.begin(),st.end(),st.begin(),(int(*)(int))std::toupper);
42
    return st;
43
};
44

    
45
/* -------------------------------------------------------------------------- */
46
/* -------------------------------------------------------------------------- */
47

    
48
string& one_util::tolower(string& st)
49
{
50
    transform(st.begin(),st.end(),st.begin(),(int(*)(int))std::tolower);
51
    return st;
52
};
53

    
54
/* -------------------------------------------------------------------------- */
55
/* -------------------------------------------------------------------------- */
56

    
57
string one_util::log_time(time_t the_time)
58
{
59
    char time_str[26];
60

    
61
#ifdef SOLARIS
62
    ctime_r(&(the_time),time_str,sizeof(char)*26);
63
#else
64
    ctime_r(&(the_time),time_str);
65
#endif
66

    
67
    time_str[24] = '\0'; // Get rid of final enter character
68

    
69
    return string(time_str);
70
};
71

    
72
/* -------------------------------------------------------------------------- */
73
/* -------------------------------------------------------------------------- */
74

    
75
string one_util::log_time()
76
{
77
    return log_time( time(0) );
78
};
79

    
80
/* -------------------------------------------------------------------------- */
81
/* -------------------------------------------------------------------------- */
82

    
83
string * one_util::base64_encode(const string& in)
84
{
85
    BIO *     bio_mem;
86
    BIO *     bio_64;
87

    
88
    char *    encoded_c;
89
    long int  size;
90

    
91
    bio_64  = BIO_new(BIO_f_base64());
92
    bio_mem = BIO_new(BIO_s_mem());
93

    
94
    BIO_push(bio_64, bio_mem);
95

    
96
    BIO_set_flags(bio_64, BIO_FLAGS_BASE64_NO_NL);
97

    
98
    BIO_write(bio_64, in.c_str(), in.length());
99

    
100
    if (BIO_flush(bio_64) != 1)
101
    {
102
        return 0;
103
    }
104

    
105
    size = BIO_get_mem_data(bio_mem,&encoded_c);
106

    
107
    string * encoded = new string(encoded_c,size);
108

    
109
    BIO_free_all(bio_64);
110

    
111
    return encoded;
112
}
113

    
114
/* -------------------------------------------------------------------------- */
115
/* -------------------------------------------------------------------------- */
116

    
117
string * one_util::base64_decode(const string& in)
118
{
119
    BIO *  bio_mem_in;
120
    BIO *  bio_mem_out;
121
    BIO *  bio_64;
122

    
123
    char inbuf[512];
124
    int  inlen;
125

    
126
    char *   decoded_c;
127
    long int size;
128

    
129
    bio_64  = BIO_new(BIO_f_base64());
130

    
131
    bio_mem_in  = BIO_new(BIO_s_mem());
132
    bio_mem_out = BIO_new(BIO_s_mem());
133

    
134
    bio_64 = BIO_push(bio_64, bio_mem_in);
135

    
136
    BIO_set_flags(bio_64, BIO_FLAGS_BASE64_NO_NL);
137

    
138
    BIO_write(bio_mem_in, in.c_str(), in.length());
139

    
140
    while((inlen = BIO_read(bio_64, inbuf, 512)) > 0)
141
    {
142
        BIO_write(bio_mem_out, inbuf, inlen);
143
    }
144

    
145
    size = BIO_get_mem_data(bio_mem_out, &decoded_c);
146

    
147
    string * decoded = new string(decoded_c, size);
148

    
149
    BIO_free_all(bio_64);
150
    BIO_free_all(bio_mem_out);
151

    
152
    return decoded;
153
}
154

    
155
/* -------------------------------------------------------------------------- */
156
/* -------------------------------------------------------------------------- */
157

    
158
string one_util::sha1_digest(const string& in)
159
{
160
    EVP_MD_CTX     mdctx;
161
    unsigned char  md_value[EVP_MAX_MD_SIZE];
162
    unsigned int   md_len;
163
    ostringstream  oss;
164

    
165
    EVP_MD_CTX_init(&mdctx);
166
    EVP_DigestInit_ex(&mdctx, EVP_sha1(), NULL);
167

    
168
    EVP_DigestUpdate(&mdctx, in.c_str(), in.length());
169

    
170
    EVP_DigestFinal_ex(&mdctx,md_value,&md_len);
171
    EVP_MD_CTX_cleanup(&mdctx);
172

    
173
    for(unsigned int i = 0; i<md_len; i++)
174
    {
175
        oss << setfill('0') << setw(2) << hex << nouppercase
176
            << (unsigned short) md_value[i];
177
    }
178

    
179
    return oss.str();
180
}
181

    
182
/* -------------------------------------------------------------------------- */
183
/* -------------------------------------------------------------------------- */
184

    
185
string * one_util::aes256cbc_encrypt(const string& in, const string password)
186
{
187
    EVP_CIPHER_CTX ctx;
188

    
189
    const unsigned char *key     = (unsigned char*) password.c_str();
190
    const unsigned char *in_data = (unsigned char*) in.c_str();
191

    
192
    unsigned char out[in.length() + AES_BLOCK_SIZE];
193

    
194
    int outlen1, outlen2;
195

    
196
    EVP_EncryptInit(&ctx, EVP_aes_256_cbc(), key, NULL);
197
    EVP_EncryptUpdate(&ctx, out, &outlen1, in_data, in.length());
198
    EVP_EncryptFinal(&ctx, out + outlen1, &outlen2);
199

    
200
    EVP_CIPHER_CTX_cleanup(&ctx);
201

    
202
    string encrypt((char*) out, (size_t)(outlen1+outlen2));
203

    
204
    return base64_encode(encrypt);;
205
}
206

    
207
/* -------------------------------------------------------------------------- */
208
/* -------------------------------------------------------------------------- */
209

    
210
string one_util::random_password()
211
{
212
    static bool init = false;
213

    
214
    ostringstream  sstr;
215

    
216
    if (!init)
217
    {
218
        srand(time(0) + rand());
219
        init = true;
220
    }
221

    
222
    sstr << rand();
223

    
224
    return sha1_digest(sstr.str());
225
}
226

    
227
/* -------------------------------------------------------------------------- */
228
/* -------------------------------------------------------------------------- */
229

    
230
vector<string> one_util::split(const string& st, char delim, bool clean_empty)
231
{
232
    vector<string>  parts;
233
    string          part;
234

    
235
    stringstream    ss(st);
236

    
237
    while (getline(ss, part, delim))
238
    {
239
        if (!(clean_empty && part.empty()))
240
        {
241
            parts.push_back(part);
242
        }
243
    }
244

    
245
    return parts;
246
}
247

    
248
/* -------------------------------------------------------------------------- */
249
/* -------------------------------------------------------------------------- */
250

    
251
string one_util::float_to_str(const float &num)
252
{
253
    ostringstream oss;
254

    
255
    if ( num == ceil(num) )
256
    {
257
        oss.precision(0);
258
    }
259
    else
260
    {
261
        oss.precision(2);
262
    }
263

    
264
    oss << fixed << num;
265

    
266
    return oss.str();
267
}
268

    
269
/* -------------------------------------------------------------------------- */
270
/* -------------------------------------------------------------------------- */
271

    
272
int one_util::regex_match(const char *pattern, const char *subject)
273
{
274
    int rc;
275
    regex_t re;
276

    
277
    rc = regcomp(&re, pattern, REG_EXTENDED|REG_NOSUB);
278

    
279
    if (rc != 0)
280
    {
281
        return(rc);
282
    }
283

    
284
    rc = regexec(&re, subject, 0, 0, 0);
285
    regfree(&re);
286

    
287
    return rc;
288
}
289

    
290
/* -------------------------------------------------------------------------- */
291
/* -------------------------------------------------------------------------- */
292

    
293
static bool not_space(int c)
294
{
295
    return std::isspace(c) == 0;
296
};
297

    
298
std::string one_util::trim(const std::string& str)
299
{
300
    std::string::const_iterator        wfirst;
301
    std::string::const_reverse_iterator rwlast;
302

    
303
    wfirst = find_if(str.begin(), str.end(), not_space);
304
    rwlast = find_if(str.rbegin(),str.rend(),not_space);
305

    
306
    std::string::const_iterator wlast(rwlast.base());
307

    
308
    std::string tstr(wfirst, wlast);
309

    
310
    return tstr;
311
}
312

    
313
/* -------------------------------------------------------------------------- */
314
/* -------------------------------------------------------------------------- */
315

    
316
std::string one_util::gsub(const std::string& st, const std::string& sfind,
317
    const std::string& srepl)
318
{
319
    std::string result = st;
320

    
321
    std::string::size_type pos = 0;
322

    
323
    size_t srepl_len = srepl.length();
324
    size_t sfind_len = sfind.length();
325

    
326
    pos = result.find(sfind, pos);
327

    
328
    while(pos != std::string::npos)
329
    {
330
        result.replace(pos, sfind_len , srepl);
331
        pos += srepl_len;
332

    
333
        pos = result.find(sfind, pos);
334
    }
335

    
336
    return result;
337
}
338

    
339
/* -------------------------------------------------------------------------- */
340
/* -------------------------------------------------------------------------- */
341

    
342
namespace one_util
343
{
344
template<>
345
void split_unique(const std::string& st, char delim, std::set<std::string>& res)
346
{
347
    std::vector<std::string>::const_iterator it;
348

    
349
    std::vector<std::string> strings = split(st, delim, true);
350

    
351
    for (it = strings.begin(); it != strings.end(); it++)
352
    {
353
        res.insert(*it);
354
    }
355
}
356
}
357

    
358
/* -------------------------------------------------------------------------- */
359
/* -------------------------------------------------------------------------- */
360

    
361
/**
362
 *  Buffer length for zlib inflate/deflate
363
 */
364
#define ZBUFFER 16384
365

    
366
std::string * one_util::zlib_compress(const std::string& in, bool base64)
367
{
368
    z_stream zs;
369

    
370
    std::ostringstream oss;
371
    unsigned char      out[ZBUFFER];
372

    
373
    std::string * zstr;
374

    
375
    if ( in.empty() )
376
    {
377
        return 0;
378
    }
379

    
380
    zs.zalloc = Z_NULL;
381
    zs.zfree  = Z_NULL;
382
    zs.opaque = Z_NULL;
383

    
384
    if ( deflateInit(&zs, Z_DEFAULT_COMPRESSION) != Z_OK )
385
    {
386
        return 0;
387
    }
388

    
389
    zs.avail_in = in.size();
390
    zs.next_in  = (unsigned char *) const_cast<char *>(in.c_str());
391

    
392
    do
393
    {
394
        zs.avail_out = ZBUFFER;
395
        zs.next_out  = out;
396

    
397
        if ( deflate(&zs, Z_FINISH) == Z_STREAM_ERROR )
398
        {
399
            deflateEnd(&zs);
400
            return 0;
401
        }
402

    
403
        oss.write((const char *)out, ZBUFFER - zs.avail_out);
404
    } while (zs.avail_out == 0);
405

    
406
    deflateEnd(&zs);
407

    
408
    if ( base64 )
409
    {
410
        zstr = one_util::base64_encode(oss.str());
411
    }
412
    else
413
    {
414
        zstr = new std::string(oss.str());
415
    }
416

    
417
    return zstr;
418
}
419

    
420
/* -------------------------------------------------------------------------- */
421
/* -------------------------------------------------------------------------- */
422

    
423
std::string * one_util::zlib_decompress(const std::string& in, bool base64)
424
{
425
    int rc;
426

    
427
    z_stream zs;
428

    
429
    std::ostringstream oss;
430
    unsigned char      out[ZBUFFER];
431

    
432
    std::string * in64;
433

    
434
    if ( in.empty() )
435
    {
436
        return 0;
437
    }
438

    
439
    zs.zalloc = Z_NULL;
440
    zs.zfree  = Z_NULL;
441
    zs.opaque = Z_NULL;
442

    
443
    zs.avail_in = 0;
444
    zs.next_in  = Z_NULL;
445

    
446
    if ( inflateInit(&zs) != Z_OK)
447
    {
448
        return 0;
449
    }
450

    
451
    if ( base64 )
452
    {
453
        in64 = one_util::base64_decode(in);
454

    
455
        if (in64 == 0)
456
        {
457
            inflateEnd(&zs);
458

    
459
            return 0;
460
        }
461

    
462
        zs.avail_in = in64->size();
463
        zs.next_in  = (unsigned char *) const_cast<char *>(in64->c_str());
464
    }
465
    else
466
    {
467
        zs.avail_in = in.size();
468
        zs.next_in  = (unsigned char *) const_cast<char *>(in.c_str());
469
    }
470

    
471
    if ( zs.avail_in <= 2 ) //At least 2 byte header
472
    {
473
        inflateEnd(&zs);
474

    
475
        if ( base64 )
476
        {
477
            delete in64;
478
        }
479

    
480
        return 0;
481
    }
482

    
483
    do
484
    {
485
        zs.avail_out = ZBUFFER;
486
        zs.next_out  = out;
487

    
488
        rc = inflate(&zs, Z_FINISH);
489

    
490
        if ( rc != Z_STREAM_END && rc != Z_OK && rc != Z_BUF_ERROR )
491
        {
492
            inflateEnd(&zs);
493

    
494
            if ( base64 )
495
            {
496
                delete in64;
497
            }
498

    
499
            return 0;
500
        }
501

    
502
        oss.write((const char *)out, ZBUFFER - zs.avail_out);
503
    } while (rc != Z_STREAM_END);
504

    
505
    inflateEnd(&zs);
506

    
507
    if ( base64 )
508
    {
509
        delete in64;
510
    }
511

    
512
    return new std::string(oss.str());
513
}
514

    
515
/* -------------------------------------------------------------------------- */
516
/* -------------------------------------------------------------------------- */
517

    
518
extern "C" void one_util::sslmutex_lock_callback(int mode, int type, char *file,
519
    int line)
520
{
521
    pthread_mutex_t * pm = SSLMutex::ssl_mutex->vmutex[type];
522

    
523
    if (mode & CRYPTO_LOCK)
524
    {
525
        pthread_mutex_lock(pm);
526
    }
527
    else
528
    {
529
        pthread_mutex_unlock(pm);
530
    }
531
}
532

    
533
extern "C" unsigned long one_util::sslmutex_id_callback()
534
{
535
    return (unsigned long) pthread_self();
536
}
537

    
538
one_util::SSLMutex * one_util::SSLMutex::ssl_mutex;
539

    
540
std::vector<pthread_mutex_t *> one_util::SSLMutex::vmutex;
541

    
542
void one_util::SSLMutex::initialize()
543
{
544
    if ( ssl_mutex == 0 )
545
    {
546
        ssl_mutex = new SSLMutex();
547
    }
548
};
549

    
550
void one_util::SSLMutex::finalize()
551
{
552
    delete ssl_mutex;
553
}
554

    
555
one_util::SSLMutex::SSLMutex()
556
{
557
    pthread_mutex_t * pm;
558
    for (int i=0; i<CRYPTO_num_locks(); i++)
559
    {
560
        pm = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t));
561
        pthread_mutex_init(pm, NULL);
562

    
563
        vmutex.push_back(pm);
564
    }
565

    
566
    CRYPTO_set_id_callback((unsigned long (*)()) sslmutex_id_callback);
567

    
568
    CRYPTO_set_locking_callback(
569
        (void (*)(int, int, const char*, int))sslmutex_lock_callback);
570
}
571

    
572
one_util::SSLMutex::~SSLMutex()
573
{
574
    for (int i=0; i<CRYPTO_num_locks(); i++)
575
    {
576
        pthread_mutex_destroy(vmutex[i]);
577
        free(vmutex[i]);
578
    }
579

    
580
    CRYPTO_set_locking_callback(NULL);
581
}
582