source: ogServer-Git/src/client.c @ 3cea4bb

Last change on this file since 3cea4bb was f537daf, checked in by OpenGnSys Support Team <soporte-og@…>, 4 years ago

#941 Use fixed length strings in og_computer and og_dbi_get_computer_info

This patch is a refactor for og_computer and og_dbi_get_computer_info.
It now uses fixed lenght strings to make it more reliable and avoid
errors if the DB is not returning a null ended string.

  • Property mode set to 100644
File size: 16.4 KB
Line 
1/*
2 * Copyright (C) 2020 Soleta Networks <info@soleta.eu>
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Affero General Public License as published by the
6 * Free Software Foundation, version 3.
7 */
8
9#include "ogAdmServer.h"
10#include "dbi.h"
11#include "utils.h"
12#include "list.h"
13#include "rest.h"
14#include "json.h"
15#include "schedule.h"
16#include <syslog.h>
17#include <sys/ioctl.h>
18#include <ifaddrs.h>
19#include <sys/types.h>
20#include <sys/stat.h>
21#include <fcntl.h>
22#include <jansson.h>
23#include <time.h>
24
25static int og_resp_probe(struct og_client *cli, json_t *data)
26{
27        const char *status = NULL;
28        const char *key;
29        json_t *value;
30        int err = 0;
31
32        if (json_typeof(data) != JSON_OBJECT)
33                return -1;
34
35        json_object_foreach(data, key, value) {
36                if (!strcmp(key, "status")) {
37                        err = og_json_parse_string(value, &status);
38                        if (err < 0)
39                                return err;
40                } else {
41                        return -1;
42                }
43        }
44
45        if (!strcmp(status, "BSY"))
46                cli->status = OG_CLIENT_STATUS_BUSY;
47        else if (!strcmp(status, "OPG"))
48                cli->status = OG_CLIENT_STATUS_OGLIVE;
49        else if (!strcmp(status, "VDI"))
50                cli->status = OG_CLIENT_STATUS_VIRTUAL;
51
52        return status ? 0 : -1;
53}
54
55static int og_resp_shell_run(struct og_client *cli, json_t *data)
56{
57        const char *output = NULL;
58        char filename[4096];
59        const char *key;
60        json_t *value;
61        int err = -1;
62        FILE *file;
63
64        if (json_typeof(data) != JSON_OBJECT)
65                return -1;
66
67        json_object_foreach(data, key, value) {
68                if (!strcmp(key, "out")) {
69                        err = og_json_parse_string(value, &output);
70                        if (err < 0)
71                                return err;
72                } else {
73                        return -1;
74                }
75        }
76
77        if (!output) {
78                syslog(LOG_ERR, "%s:%d: malformed json response\n",
79                       __FILE__, __LINE__);
80                return -1;
81        }
82
83        sprintf(filename, "/tmp/_Seconsola_%s", inet_ntoa(cli->addr.sin_addr));
84        file = fopen(filename, "wt");
85        if (!file) {
86                syslog(LOG_ERR, "cannot open file %s: %s\n",
87                       filename, strerror(errno));
88                return -1;
89        }
90
91        fprintf(file, "%s", output);
92        fclose(file);
93
94        return 0;
95}
96
97struct og_computer_legacy  {
98        char center[OG_DB_INT_MAXLEN + 1];
99        char id[OG_DB_INT_MAXLEN + 1];
100        char hardware[8192];
101};
102
103static int og_resp_hardware(json_t *data, struct og_client *cli)
104{
105        struct og_computer_legacy legacy = {};
106        struct og_computer computer = {};
107        const char *hardware = NULL;
108        struct og_dbi *dbi;
109        const char *key;
110        json_t *value;
111        int err = 0;
112        bool res;
113
114        if (json_typeof(data) != JSON_OBJECT)
115                return -1;
116
117        json_object_foreach(data, key, value) {
118                if (!strcmp(key, "hardware")) {
119                        err = og_json_parse_string(value, &hardware);
120                        if (err < 0)
121                                return -1;
122                } else {
123                        return -1;
124                }
125        }
126
127        if (!hardware) {
128                syslog(LOG_ERR, "malformed response json\n");
129                return -1;
130        }
131
132        dbi = og_dbi_open(&dbi_config);
133        if (!dbi) {
134                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
135                       __func__, __LINE__);
136                return -1;
137        }
138
139        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
140        if (err < 0) {
141                og_dbi_close(dbi);
142                return -1;
143        }
144
145        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
146        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
147        snprintf(legacy.hardware, sizeof(legacy.hardware), "%s", hardware);
148
149        res = actualizaHardware(dbi, legacy.hardware, legacy.id, computer.name,
150                                legacy.center);
151        og_dbi_close(dbi);
152
153        if (!res) {
154                syslog(LOG_ERR, "Problem updating client configuration\n");
155                return -1;
156        }
157
158        return 0;
159}
160
161struct og_software_legacy {
162        char software[8192];
163        char center[OG_DB_INT_MAXLEN + 1];
164        char part[OG_DB_SMALLINT_MAXLEN + 1];
165        char id[OG_DB_INT_MAXLEN + 1];
166};
167
168static int og_resp_software(json_t *data, struct og_client *cli)
169{
170        struct og_software_legacy legacy = {};
171        struct og_computer computer = {};
172        const char *partition = NULL;
173        const char *software = NULL;
174        struct og_dbi *dbi;
175        const char *key;
176        json_t *value;
177        int err = 0;
178        bool res;
179
180        if (json_typeof(data) != JSON_OBJECT)
181                return -1;
182
183        json_object_foreach(data, key, value) {
184                if (!strcmp(key, "software"))
185                        err = og_json_parse_string(value, &software);
186                else if (!strcmp(key, "partition"))
187                        err = og_json_parse_string(value, &partition);
188                else
189                        return -1;
190
191                if (err < 0)
192                        return -1;
193        }
194
195        if (!software || !partition) {
196                syslog(LOG_ERR, "malformed response json\n");
197                return -1;
198        }
199
200        dbi = og_dbi_open(&dbi_config);
201        if (!dbi) {
202                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
203                       __func__, __LINE__);
204                return -1;
205        }
206
207        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
208        if (err < 0) {
209                og_dbi_close(dbi);
210                return -1;
211        }
212
213        snprintf(legacy.software, sizeof(legacy.software), "%s", software);
214        snprintf(legacy.part, sizeof(legacy.part), "%s", partition);
215        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
216        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
217
218        res = actualizaSoftware(dbi, legacy.software, legacy.part, legacy.id,
219                                computer.name, legacy.center);
220        og_dbi_close(dbi);
221
222        if (!res) {
223                syslog(LOG_ERR, "Problem updating client configuration\n");
224                return -1;
225        }
226
227        return 0;
228}
229
230#define OG_PARAMS_RESP_REFRESH  (OG_PARAM_PART_DISK |           \
231                                 OG_PARAM_PART_NUMBER |         \
232                                 OG_PARAM_PART_CODE |           \
233                                 OG_PARAM_PART_FILESYSTEM |     \
234                                 OG_PARAM_PART_OS |             \
235                                 OG_PARAM_PART_SIZE |           \
236                                 OG_PARAM_PART_USED_SIZE)
237
238static int og_json_parse_partition_array(json_t *value,
239                                         struct og_partition *partitions)
240{
241        json_t *element;
242        int i, err;
243
244        if (json_typeof(value) != JSON_ARRAY)
245                return -1;
246
247        for (i = 0; i < json_array_size(value) && i < OG_PARTITION_MAX; i++) {
248                element = json_array_get(value, i);
249
250                err = og_json_parse_partition(element, &partitions[i],
251                                              OG_PARAMS_RESP_REFRESH);
252                if (err < 0)
253                        return err;
254        }
255
256        return 0;
257}
258
259static int og_dbi_queue_autorun(uint32_t computer_id, uint32_t proc_id)
260{
261        struct og_task dummy_task = {
262                .scope          = computer_id,
263                .type_scope     = AMBITO_ORDENADORES,
264                .procedure_id   = proc_id,
265        };
266        struct og_dbi *dbi;
267
268        dbi = og_dbi_open(&dbi_config);
269        if (!dbi) {
270                syslog(LOG_ERR, "cannot open connection database "
271                                "(%s:%d)\n", __func__, __LINE__);
272                return -1;
273        }
274        if (og_dbi_queue_procedure(dbi, &dummy_task)) {
275                og_dbi_close(dbi);
276                return -1;
277        }
278        og_dbi_close(dbi);
279
280        return 0;
281}
282
283static int og_resp_refresh(json_t *data, struct og_client *cli)
284{
285        struct og_partition partitions[OG_PARTITION_MAX] = {};
286        const char *serial_number = NULL;
287        struct og_computer computer = {};
288        struct og_partition disk_setup;
289        char cfg[1024] = {};
290        struct og_dbi *dbi;
291        const char *key;
292        unsigned int i;
293        json_t *value;
294        int err = 0;
295        bool res;
296
297        if (json_typeof(data) != JSON_OBJECT)
298                return -1;
299
300        json_object_foreach(data, key, value) {
301                if (!strcmp(key, "disk_setup")) {
302                        err = og_json_parse_partition(value,
303                                                      &disk_setup,
304                                                      OG_PARAMS_RESP_REFRESH);
305                } else if (!strcmp(key, "partition_setup")) {
306                        err = og_json_parse_partition_array(value, partitions);
307                } else if (!strcmp(key, "serial_number")) {
308                        err = og_json_parse_string(value, &serial_number);
309                } else {
310                        return -1;
311                }
312
313                if (err < 0)
314                        return err;
315        }
316
317        if (strlen(serial_number) > 0)
318                snprintf(cfg, sizeof(cfg), "ser=%s\n", serial_number);
319
320        if (!disk_setup.disk || !disk_setup.number || !disk_setup.code ||
321            !disk_setup.filesystem || !disk_setup.os || !disk_setup.size ||
322            !disk_setup.used_size)
323                return -1;
324
325        snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
326                 "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
327                 disk_setup.disk, disk_setup.number, disk_setup.code,
328                 disk_setup.filesystem, disk_setup.os, disk_setup.size,
329                 disk_setup.used_size);
330
331        for (i = 0; i < OG_PARTITION_MAX; i++) {
332                if (!partitions[i].disk || !partitions[i].number ||
333                    !partitions[i].code || !partitions[i].filesystem ||
334                    !partitions[i].os || !partitions[i].size ||
335                    !partitions[i].used_size)
336                        continue;
337
338                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
339                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
340                         partitions[i].disk, partitions[i].number,
341                         partitions[i].code, partitions[i].filesystem,
342                         partitions[i].os, partitions[i].size,
343                         partitions[i].used_size);
344        }
345
346        dbi = og_dbi_open(&dbi_config);
347        if (!dbi) {
348                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
349                                  __func__, __LINE__);
350                return -1;
351        }
352
353        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
354        if (err < 0) {
355                og_dbi_close(dbi);
356                return -1;
357        }
358
359        res = actualizaConfiguracion(dbi, cfg, computer.id);
360        og_dbi_close(dbi);
361
362        if (!res) {
363                syslog(LOG_ERR, "Problem updating client configuration\n");
364                return -1;
365        }
366
367        if (!cli->autorun && computer.procedure_id) {
368                cli->autorun = true;
369
370                if (og_dbi_queue_autorun(computer.id, computer.procedure_id))
371                        return -1;
372        }
373
374        return 0;
375}
376
377static int update_image_info(struct og_dbi *dbi, const char *image_id,
378                             const char *clonator, const char *compressor,
379                             const char *filesystem, const uint64_t datasize)
380{
381        const char *msglog;
382        dbi_result result;
383
384        result = dbi_conn_queryf(dbi->conn,
385                "UPDATE imagenes"
386                "   SET clonator='%s', compressor='%s',"
387                "       filesystem='%s', datasize=%lld"
388                " WHERE idimagen=%s", clonator, compressor, filesystem,
389                datasize, image_id);
390
391        if (!result) {
392                dbi_conn_error(dbi->conn, &msglog);
393                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
394                       __func__, __LINE__, msglog);
395                return -1;
396        }
397        dbi_result_free(result);
398
399        return 0;
400}
401
402static int og_resp_image_create(json_t *data, struct og_client *cli)
403{
404        struct og_software_legacy soft_legacy;
405        struct og_image_legacy img_legacy;
406        struct og_computer computer = {};
407        const char *compressor = NULL;
408        const char *filesystem = NULL;
409        const char *partition = NULL;
410        const char *software = NULL;
411        const char *image_id = NULL;
412        const char *clonator = NULL;
413        const char *disk = NULL;
414        const char *code = NULL;
415        const char *name = NULL;
416        const char *repo = NULL;
417        uint64_t datasize = 0;
418        struct og_dbi *dbi;
419        const char *key;
420        json_t *value;
421        int err = 0;
422        bool res;
423
424        if (json_typeof(data) != JSON_OBJECT)
425                return -1;
426
427        json_object_foreach(data, key, value) {
428                if (!strcmp(key, "software"))
429                        err = og_json_parse_string(value, &software);
430                else if (!strcmp(key, "partition"))
431                        err = og_json_parse_string(value, &partition);
432                else if (!strcmp(key, "disk"))
433                        err = og_json_parse_string(value, &disk);
434                else if (!strcmp(key, "code"))
435                        err = og_json_parse_string(value, &code);
436                else if (!strcmp(key, "id"))
437                        err = og_json_parse_string(value, &image_id);
438                else if (!strcmp(key, "name"))
439                        err = og_json_parse_string(value, &name);
440                else if (!strcmp(key, "repository"))
441                        err = og_json_parse_string(value, &repo);
442                else if (!strcmp(key, "clonator"))
443                        err = og_json_parse_string(value, &clonator);
444                else if (!strcmp(key, "compressor"))
445                        err = og_json_parse_string(value, &compressor);
446                else if (!strcmp(key, "filesystem"))
447                        err = og_json_parse_string(value, &filesystem);
448                else if (!strcmp(key, "datasize"))
449                        err = og_json_parse_uint64(value, &datasize);
450                else
451                        return -1;
452
453                if (err < 0)
454                        return err;
455        }
456
457        if (!software || !partition || !disk || !code || !image_id || !name ||
458            !repo || !clonator || !compressor || !filesystem || !datasize) {
459                syslog(LOG_ERR, "malformed response json\n");
460                return -1;
461        }
462
463        dbi = og_dbi_open(&dbi_config);
464        if (!dbi) {
465                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
466                       __func__, __LINE__);
467                return -1;
468        }
469
470        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
471        if (err < 0) {
472                og_dbi_close(dbi);
473                return -1;
474        }
475
476        snprintf(soft_legacy.center, sizeof(soft_legacy.center), "%d",
477                 computer.center);
478        snprintf(soft_legacy.software, sizeof(soft_legacy.software), "%s",
479                 software);
480        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
481                 image_id);
482        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
483        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
484        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
485        snprintf(img_legacy.code, sizeof(img_legacy.code), "%s", code);
486        snprintf(img_legacy.name, sizeof(img_legacy.name), "%s", name);
487        snprintf(img_legacy.repo, sizeof(img_legacy.repo), "%s", repo);
488
489        res = actualizaSoftware(dbi,
490                                soft_legacy.software,
491                                img_legacy.part,
492                                soft_legacy.id,
493                                computer.name,
494                                soft_legacy.center);
495        if (!res) {
496                og_dbi_close(dbi);
497                syslog(LOG_ERR, "Problem updating client configuration\n");
498                return -1;
499        }
500
501        res = actualizaCreacionImagen(dbi,
502                                      img_legacy.image_id,
503                                      img_legacy.disk,
504                                      img_legacy.part,
505                                      img_legacy.code,
506                                      img_legacy.repo,
507                                      soft_legacy.id);
508        if (!res) {
509                og_dbi_close(dbi);
510                syslog(LOG_ERR, "Problem updating client configuration\n");
511                return -1;
512        }
513
514        res = update_image_info(dbi, image_id, clonator, compressor,
515                                filesystem, datasize);
516        og_dbi_close(dbi);
517
518        if (res) {
519                syslog(LOG_ERR, "Problem updating image info\n");
520                return -1;
521        }
522
523        return 0;
524}
525
526static int og_resp_image_restore(json_t *data, struct og_client *cli)
527{
528        struct og_software_legacy soft_legacy;
529        struct og_image_legacy img_legacy;
530        struct og_computer computer = {};
531        const char *partition = NULL;
532        const char *image_id = NULL;
533        const char *disk = NULL;
534        dbi_result query_result;
535        struct og_dbi *dbi;
536        const char *key;
537        json_t *value;
538        int err = 0;
539        bool res;
540
541        if (json_typeof(data) != JSON_OBJECT)
542                return -1;
543
544        json_object_foreach(data, key, value) {
545                if (!strcmp(key, "partition"))
546                        err = og_json_parse_string(value, &partition);
547                else if (!strcmp(key, "disk"))
548                        err = og_json_parse_string(value, &disk);
549                else if (!strcmp(key, "image_id"))
550                        err = og_json_parse_string(value, &image_id);
551                else
552                        return -1;
553
554                if (err < 0)
555                        return err;
556        }
557
558        if (!partition || !disk || !image_id) {
559                syslog(LOG_ERR, "malformed response json\n");
560                return -1;
561        }
562
563        dbi = og_dbi_open(&dbi_config);
564        if (!dbi) {
565                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
566                       __func__, __LINE__);
567                return -1;
568        }
569
570        query_result = dbi_conn_queryf(dbi->conn,
571                                       "SELECT idperfilsoft FROM imagenes "
572                                       " WHERE idimagen='%s'",
573                                       image_id);
574        if (!query_result) {
575                og_dbi_close(dbi);
576                syslog(LOG_ERR, "failed to query database\n");
577                return -1;
578        }
579        if (!dbi_result_next_row(query_result)) {
580                dbi_result_free(query_result);
581                og_dbi_close(dbi);
582                syslog(LOG_ERR, "software profile does not exist in database\n");
583                return -1;
584        }
585        snprintf(img_legacy.software_id, sizeof(img_legacy.software_id),
586                 "%d", dbi_result_get_uint(query_result, "idperfilsoft"));
587        dbi_result_free(query_result);
588
589        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
590        if (err < 0) {
591                og_dbi_close(dbi);
592                return -1;
593        }
594
595        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
596                 image_id);
597        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
598        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
599        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
600
601        res = actualizaRestauracionImagen(dbi,
602                                          img_legacy.image_id,
603                                          img_legacy.disk,
604                                          img_legacy.part,
605                                          soft_legacy.id,
606                                          img_legacy.software_id);
607        og_dbi_close(dbi);
608
609        if (!res) {
610                syslog(LOG_ERR, "Problem updating client configuration\n");
611                return -1;
612        }
613
614        return 0;
615}
616
617int og_agent_state_process_response(struct og_client *cli)
618{
619        json_error_t json_err;
620        json_t *root;
621        int err = -1;
622        char *body;
623
624        if (!strncmp(cli->buf, "HTTP/1.0 202 Accepted",
625                     strlen("HTTP/1.0 202 Accepted"))) {
626                og_dbi_update_action(cli->last_cmd_id, true);
627                cli->last_cmd_id = 0;
628                return 1;
629        }
630
631        if (strncmp(cli->buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) {
632                og_dbi_update_action(cli->last_cmd_id, false);
633                cli->last_cmd_id = 0;
634                return -1;
635        }
636        og_dbi_update_action(cli->last_cmd_id, true);
637        cli->last_cmd_id = 0;
638
639        if (!cli->content_length) {
640                cli->last_cmd = OG_CMD_UNSPEC;
641                return 0;
642        }
643
644        body = strstr(cli->buf, "\r\n\r\n") + 4;
645
646        root = json_loads(body, 0, &json_err);
647        if (!root) {
648                syslog(LOG_ERR, "%s:%d: malformed json line %d: %s\n",
649                       __FILE__, __LINE__, json_err.line, json_err.text);
650                return -1;
651        }
652
653        switch (cli->last_cmd) {
654        case OG_CMD_PROBE:
655                err = og_resp_probe(cli, root);
656                break;
657        case OG_CMD_SHELL_RUN:
658                err = og_resp_shell_run(cli, root);
659                break;
660        case OG_CMD_HARDWARE:
661                err = og_resp_hardware(root, cli);
662                break;
663        case OG_CMD_SOFTWARE:
664                err = og_resp_software(root, cli);
665                break;
666        case OG_CMD_REFRESH:
667                err = og_resp_refresh(root, cli);
668                break;
669        case OG_CMD_SETUP:
670                err = og_resp_refresh(root, cli);
671                break;
672        case OG_CMD_IMAGE_CREATE:
673                err = og_resp_image_create(root, cli);
674                break;
675        case OG_CMD_IMAGE_RESTORE:
676                err = og_resp_image_restore(root, cli);
677                break;
678        default:
679                err = -1;
680                break;
681        }
682
683        cli->last_cmd = OG_CMD_UNSPEC;
684
685        return err;
686}
Note: See TracBrowser for help on using the repository browser.