Statistics
| Branch: | Tag: | Revision:

one / src / authm / AuthManager.cc @ ae53d437

History | View | Annotate | Download (13.3 KB)

1
/* -------------------------------------------------------------------------- */
2
/* Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org)             */
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 "AuthManager.h"
18
#include "NebulaLog.h"
19

    
20
#include "Nebula.h"
21

    
22
#include <openssl/sha.h>
23
#include <openssl/hmac.h>
24
#include <openssl/evp.h>
25
#include <openssl/bio.h>
26
#include <openssl/buffer.h>
27

    
28
/* -------------------------------------------------------------------------- */
29
/* -------------------------------------------------------------------------- */
30

    
31
time_t AuthManager::_time_out;
32

    
33
const char * AuthManager::auth_driver_name = "auth_exe";
34

    
35
/* -------------------------------------------------------------------------- */
36
/* -------------------------------------------------------------------------- */
37

    
38
string * AuthRequest::base64_encode(const string& in)
39
{
40
    BIO *     bio_mem;
41
    BIO *     bio_64;
42

    
43
    char *    encoded_c;
44
    long int  size;
45

    
46
    bio_64  = BIO_new(BIO_f_base64());
47
    bio_mem = BIO_new(BIO_s_mem());
48

    
49
    BIO_push(bio_64, bio_mem);
50

    
51
    BIO_set_flags(bio_64,BIO_FLAGS_BASE64_NO_NL);
52

    
53
    BIO_write(bio_64, in.c_str(), in.length());
54

    
55
    if (BIO_flush(bio_64) != 1)
56
    {
57
        return 0;
58
    }
59

    
60
    size = BIO_get_mem_data(bio_mem,&encoded_c);
61

    
62
    string * encoded = new string(encoded_c,size);
63

    
64
    BIO_free_all(bio_64);
65

    
66
    return encoded;
67
}
68

    
69
/* -------------------------------------------------------------------------- */
70
/* -------------------------------------------------------------------------- */
71

    
72
void AuthRequest::add_auth(Object        ob,
73
                           const string& ob_id,
74
                           Operation     op,
75
                           int           owner,
76
                           bool          pub)
77
{
78
    ostringstream oss;
79
    bool          auth;
80

    
81
    switch (ob)
82
    {
83
        case VM:       oss << "VM:" ; break;
84
        case HOST:     oss << "HOST:" ; break;
85
        case NET:      oss << "NET:" ; break;
86
        case IMAGE:    oss << "IMAGE:" ; break;
87
        case USER:     oss << "USER:" ; break;
88
        case CLUSTER:  oss << "CLUSTER:" ; break;
89
        case TEMPLATE: oss << "TEMPLATE:" ; break;
90
        case GROUP:    oss << "GROUP:" ; break;
91
    }
92

    
93
    if (op == CREATE || op == INSTANTIATE) //encode the ob_id, it is a template
94
    {
95
        string * encoded_id = base64_encode(ob_id);
96

    
97
        if (encoded_id != 0)
98
        {
99
            oss << *encoded_id << ":";
100
            delete (encoded_id);
101
        }
102
        else
103
        {
104
            oss << "-:";
105
        }
106
    }
107
    else
108
    {
109
        oss << ob_id << ":";
110
    }
111

    
112
    switch (op)
113
    {
114
        case CREATE:
115
            oss << "CREATE:" ;
116
            break;
117

    
118
        case DELETE:
119
            oss << "DELETE:" ;
120
            break;
121

    
122
        case USE:
123
            oss << "USE:" ;
124
            break;
125

    
126
        case MANAGE:
127
            oss << "MANAGE:" ;
128
            break;
129
            
130
        case INFO:
131
            oss << "INFO:" ;
132
            break;
133

    
134
        case INSTANTIATE:
135
            oss << "INSTANTIATE:" ;
136
            break;
137
    }
138

    
139
    oss << owner << ":" << pub;
140

    
141
    // -------------------------------------------------------------------------
142
    // Authorize the request for self authorization
143
    // -------------------------------------------------------------------------
144

    
145
    if ( uid == 0 )
146
    {
147
        auth = true;
148
    }
149
    else
150
    {
151
        auth = false;
152

    
153
        switch (op)
154
        {
155
            case CREATE:
156
                if ( ob == VM || ob == NET || ob == IMAGE || ob == TEMPLATE )
157
                {
158
                    auth = true;
159
                }
160
                break;
161

    
162
            case INSTANTIATE:
163
                if ( ob == VM )
164
                {
165
                    auth = true;
166
                }
167
                break;
168

    
169
            case DELETE:
170
                auth = owner == uid;
171
                break;
172

    
173
            case USE:
174
                if (ob == NET || ob == IMAGE || ob == TEMPLATE)
175
                {
176
                    auth = (owner == uid) || pub;
177
                }
178
                else if (ob == HOST)
179
                {
180
                    auth = true;
181
                }
182
                break;
183

    
184
            case MANAGE:
185
                auth = owner == uid;
186
                break;
187
                
188
            case INFO: // This is for completeness, as the only INFO existing 
189
                       // is for UserPool, and just oneadmin can see it
190
                break;
191
        }
192
    }
193

    
194
    self_authorize = self_authorize && auth;
195

    
196
    auths.push_back(oss.str());
197
}
198

    
199
/* -------------------------------------------------------------------------- */
200
/* -------------------------------------------------------------------------- */
201

    
202
extern "C" void * authm_action_loop(void *arg)
203
{
204
    AuthManager *  authm;
205

    
206
    if ( arg == 0 )
207
    {
208
        return 0;
209
    }
210

    
211
    authm = static_cast<AuthManager *>(arg);
212

    
213
    NebulaLog::log("AuM",Log::INFO,"Authorization Manager started.");
214

    
215
    authm->am.loop(authm->timer_period,0);
216

    
217
    NebulaLog::log("AuM",Log::INFO,"Authorization Manager stopped.");
218

    
219
    return 0;
220
}
221

    
222
/* -------------------------------------------------------------------------- */
223

    
224
int AuthManager::start()
225
{
226
    int               rc;
227
    pthread_attr_t    pattr;
228

    
229
    rc = MadManager::start();
230

    
231
    if ( rc != 0 )
232
    {
233
        return -1;
234
    }
235

    
236
    NebulaLog::log("AuM",Log::INFO,"Starting Auth Manager...");
237

    
238
    pthread_attr_init (&pattr);
239
    pthread_attr_setdetachstate (&pattr, PTHREAD_CREATE_JOINABLE);
240

    
241
    rc = pthread_create(&authm_thread,&pattr,authm_action_loop,(void *) this);
242

    
243
    return rc;
244
}
245

    
246
/* -------------------------------------------------------------------------- */
247
/* -------------------------------------------------------------------------- */
248

    
249
void AuthManager::trigger(Actions action, AuthRequest * request)
250
{
251
    string  aname;
252

    
253
    switch (action)
254
    {
255
    case AUTHENTICATE:
256
        aname = "AUTHENTICATE";
257
        break;
258

    
259
    case AUTHORIZE:
260
        aname = "AUTHORIZE";
261
        break;
262

    
263
    case FINALIZE:
264
        aname = ACTION_FINALIZE;
265
        break;
266

    
267
    default:
268
        return;
269
    }
270

    
271
    am.trigger(aname,request);
272
}
273

    
274
/* -------------------------------------------------------------------------- */
275
/* -------------------------------------------------------------------------- */
276

    
277
void AuthManager::do_action(const string &action, void * arg)
278
{
279
    AuthRequest * request;
280

    
281
    request  = static_cast<AuthRequest *>(arg);
282

    
283
    if (action == "AUTHENTICATE" && request != 0)
284
    {
285
        authenticate_action(request);
286
    }
287
    else if (action == "AUTHORIZE"  && request != 0)
288
    {
289
        authorize_action(request);
290
    }
291
    else if (action == ACTION_TIMER)
292
    {
293
        timer_action();
294
    }
295
    else if (action == ACTION_FINALIZE)
296
    {
297
        NebulaLog::log("AuM",Log::INFO,"Stopping Authorization Manager...");
298

    
299
        MadManager::stop();
300
    }
301
    else
302
    {
303
        ostringstream oss;
304
        oss << "Unknown action name: " << action;
305

    
306
        NebulaLog::log("AuM", Log::ERROR, oss);
307
    }
308
}
309

    
310
/* -------------------------------------------------------------------------- */
311
/* -------------------------------------------------------------------------- */
312

    
313
void AuthManager::authenticate_action(AuthRequest * ar)
314
{
315
    const AuthManagerDriver * authm_md;
316

    
317
    // ------------------------------------------------------------------------
318
    // Get the driver
319
    // ------------------------------------------------------------------------
320

    
321
    authm_md = get();
322

    
323
    if (authm_md == 0)
324
    {
325
        goto error_driver;
326
    }
327

    
328
    // ------------------------------------------------------------------------
329
    // Queue the request
330
    // ------------------------------------------------------------------------
331

    
332
    ar->id = add_request(ar);
333

    
334
    // ------------------------------------------------------------------------
335
    // Make the request to the driver
336
    // ---- --------------------------------------------------------------------
337

    
338

    
339
    authm_md->authenticate(ar->id,
340
                           ar->uid,
341
                           ar->username,
342
                           ar->password,
343
                           ar->session);
344
    return;
345

    
346
error_driver:
347
    ar->result  = false;
348
    ar->message = "Could not find Authorization driver";
349
    ar->notify();
350
}
351

    
352
/* -------------------------------------------------------------------------- */
353
/* -------------------------------------------------------------------------- */
354

    
355
void AuthManager::authorize_action(AuthRequest * ar)
356
{
357
    const AuthManagerDriver * authm_md;
358
    string auths;
359

    
360
    // ------------------------------------------------------------------------
361
    // Get the driver
362
    // ------------------------------------------------------------------------
363

    
364
    authm_md = get();
365

    
366
    if (authm_md == 0)
367
    {
368
        goto error_driver;
369
    }
370

    
371
    // ------------------------------------------------------------------------
372
    // Queue the request
373
    // ------------------------------------------------------------------------
374

    
375
    ar->id = add_request(ar);
376

    
377
    // ------------------------------------------------------------------------
378
    // Make the request to the driver
379
    // ------------------------------------------------------------------------
380

    
381
    auths = ar->get_auths();
382

    
383
    authm_md->authorize(ar->id, ar->uid, auths);
384

    
385
    return;
386

    
387
error_driver:
388
    ar->result  = false;
389
    ar->message = "Could not find Authorization driver";
390
    ar->notify();
391
}
392
/* -------------------------------------------------------------------------- */
393
/* -------------------------------------------------------------------------- */
394

    
395
void AuthManager::timer_action()
396
{
397
    map<int,AuthRequest *>::iterator it;
398

    
399
    time_t the_time = time(0);
400

    
401
    lock();
402

    
403
    for (it=auth_requests.begin();it!=auth_requests.end();it++)
404
    {
405
        if (the_time > it->second->time_out)
406
        {
407
            AuthRequest * ar = it->second;
408
            auth_requests.erase(it);
409

    
410
            ar->result  = false;
411
            ar->timeout = true;
412
            ar->message = "Auth request timeout";
413

    
414
            ar->notify();
415
        }
416
    }
417

    
418
    unlock();
419

    
420
}
421

    
422
/* -------------------------------------------------------------------------- */
423
/* -------------------------------------------------------------------------- */
424

    
425
int AuthManager::add_request(AuthRequest *ar)
426
{
427
    static int auth_id = 0;
428
    int id;
429

    
430
    lock();
431

    
432
    id = auth_id++;
433

    
434
    auth_requests.insert(auth_requests.end(),make_pair(id,ar));
435

    
436
    unlock();
437

    
438
    return id;
439
}
440

    
441
/* -------------------------------------------------------------------------- */
442
/* -------------------------------------------------------------------------- */
443

    
444
AuthRequest * AuthManager::get_request(int id)
445
{
446
    AuthRequest * ar = 0;
447
    map<int,AuthRequest *>::iterator it;
448
    ostringstream oss;
449

    
450
    lock();
451

    
452
    it=auth_requests.find(id);
453

    
454
    if ( it != auth_requests.end())
455
    {
456
        ar = it->second;
457

    
458
        auth_requests.erase(it);
459
    }
460

    
461
    unlock();
462

    
463
    return ar;
464
}
465

    
466
/* -------------------------------------------------------------------------- */
467
/* -------------------------------------------------------------------------- */
468

    
469
void AuthManager::notify_request(int auth_id,bool result,const string& message)
470
{
471

    
472
    AuthRequest * ar;
473

    
474
    ar = get_request(auth_id);
475

    
476
    if ( ar == 0 )
477
    {
478
        return;
479
    }
480

    
481
    ar->result = result;
482
    ar->message= message;
483

    
484
    ar->notify();
485
}
486

    
487
/* ************************************************************************** */
488
/* MAD Loading                                                                */
489
/* ************************************************************************** */
490

    
491
void AuthManager::load_mads(int uid)
492
{
493
    ostringstream                   oss;
494
    const VectorAttribute *         vattr;
495
    int                             rc;
496
    string                          name;
497
    AuthManagerDriver *             authm_driver = 0;
498

    
499
    oss << "Loading Auth. Manager driver.";
500

    
501
    NebulaLog::log("AuM",Log::INFO,oss);
502

    
503
    vattr = static_cast<const VectorAttribute *>(mad_conf[0]);
504

    
505
    if ( vattr == 0 )
506
    {
507
        NebulaLog::log("AuM",Log::ERROR,"Failed to load Auth. Manager driver.");
508
        return;
509
    }
510

    
511
    VectorAttribute auth_conf("AUTH_MAD",vattr->value());
512

    
513
    auth_conf.replace("NAME",auth_driver_name);
514

    
515
    authm_driver = new AuthManagerDriver(uid,auth_conf.value(),(uid!=0),this);
516

    
517
    rc = add(authm_driver);
518

    
519
    if ( rc == 0 )
520
    {
521
        oss.str("");
522
        oss << "\tAuth Manager loaded";
523

    
524
        NebulaLog::log("AuM",Log::INFO,oss);
525
    }
526
}