source: ogServer-Git/src/client.c @ 27fbc65

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

#1004 Fix integer overflow in datasize

ogClient datasize is now in bytes, update format to fix a possible overflow.

  • Property mode set to 100644
File size: 16.8 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                og_dbi_free_computer_info(&computer);
137                return -1;
138        }
139
140        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
141        if (err < 0) {
142                og_dbi_close(dbi);
143                return -1;
144        }
145
146        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
147        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
148        snprintf(legacy.hardware, sizeof(legacy.hardware), "%s", hardware);
149
150        res = actualizaHardware(dbi, legacy.hardware, legacy.id, computer.name,
151                                legacy.center);
152        og_dbi_close(dbi);
153        og_dbi_free_computer_info(&computer);
154
155        if (!res) {
156                syslog(LOG_ERR, "Problem updating client configuration\n");
157                return -1;
158        }
159
160        return 0;
161}
162
163struct og_software_legacy {
164        char software[8192];
165        char center[OG_DB_INT_MAXLEN + 1];
166        char part[OG_DB_SMALLINT_MAXLEN + 1];
167        char id[OG_DB_INT_MAXLEN + 1];
168};
169
170static int og_resp_software(json_t *data, struct og_client *cli)
171{
172        struct og_software_legacy legacy = {};
173        struct og_computer computer = {};
174        const char *partition = NULL;
175        const char *software = NULL;
176        struct og_dbi *dbi;
177        const char *key;
178        json_t *value;
179        int err = 0;
180        bool res;
181
182        if (json_typeof(data) != JSON_OBJECT)
183                return -1;
184
185        json_object_foreach(data, key, value) {
186                if (!strcmp(key, "software"))
187                        err = og_json_parse_string(value, &software);
188                else if (!strcmp(key, "partition"))
189                        err = og_json_parse_string(value, &partition);
190                else
191                        return -1;
192
193                if (err < 0)
194                        return -1;
195        }
196
197        if (!software || !partition) {
198                syslog(LOG_ERR, "malformed response json\n");
199                return -1;
200        }
201
202        dbi = og_dbi_open(&dbi_config);
203        if (!dbi) {
204                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
205                       __func__, __LINE__);
206                og_dbi_free_computer_info(&computer);
207                return -1;
208        }
209
210        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
211        if (err < 0) {
212                og_dbi_close(dbi);
213                return -1;
214        }
215
216        snprintf(legacy.software, sizeof(legacy.software), "%s", software);
217        snprintf(legacy.part, sizeof(legacy.part), "%s", partition);
218        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
219        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
220
221        res = actualizaSoftware(dbi, legacy.software, legacy.part, legacy.id,
222                                computer.name, legacy.center);
223        og_dbi_close(dbi);
224        og_dbi_free_computer_info(&computer);
225
226        if (!res) {
227                syslog(LOG_ERR, "Problem updating client configuration\n");
228                return -1;
229        }
230
231        return 0;
232}
233
234#define OG_PARAMS_RESP_REFRESH  (OG_PARAM_PART_DISK |           \
235                                 OG_PARAM_PART_NUMBER |         \
236                                 OG_PARAM_PART_CODE |           \
237                                 OG_PARAM_PART_FILESYSTEM |     \
238                                 OG_PARAM_PART_OS |             \
239                                 OG_PARAM_PART_SIZE |           \
240                                 OG_PARAM_PART_USED_SIZE)
241
242static int og_json_parse_partition_array(json_t *value,
243                                         struct og_partition *partitions)
244{
245        json_t *element;
246        int i, err;
247
248        if (json_typeof(value) != JSON_ARRAY)
249                return -1;
250
251        for (i = 0; i < json_array_size(value) && i < OG_PARTITION_MAX; i++) {
252                element = json_array_get(value, i);
253
254                err = og_json_parse_partition(element, &partitions[i],
255                                              OG_PARAMS_RESP_REFRESH);
256                if (err < 0)
257                        return err;
258        }
259
260        return 0;
261}
262
263static int og_dbi_queue_autorun(uint32_t computer_id, uint32_t proc_id)
264{
265        struct og_task dummy_task = {
266                .scope          = computer_id,
267                .type_scope     = AMBITO_ORDENADORES,
268                .procedure_id   = proc_id,
269        };
270        struct og_dbi *dbi;
271
272        dbi = og_dbi_open(&dbi_config);
273        if (!dbi) {
274                syslog(LOG_ERR, "cannot open connection database "
275                                "(%s:%d)\n", __func__, __LINE__);
276                return -1;
277        }
278        if (og_dbi_queue_procedure(dbi, &dummy_task)) {
279                og_dbi_close(dbi);
280                return -1;
281        }
282        og_dbi_close(dbi);
283
284        return 0;
285}
286
287static int og_resp_refresh(json_t *data, struct og_client *cli)
288{
289        struct og_partition partitions[OG_PARTITION_MAX] = {};
290        const char *serial_number = NULL;
291        struct og_computer computer = {};
292        struct og_partition disk_setup;
293        char cfg[1024] = {};
294        struct og_dbi *dbi;
295        const char *key;
296        unsigned int i;
297        json_t *value;
298        int err = 0;
299        bool res;
300
301        if (json_typeof(data) != JSON_OBJECT)
302                return -1;
303
304        json_object_foreach(data, key, value) {
305                if (!strcmp(key, "disk_setup")) {
306                        err = og_json_parse_partition(value,
307                                                      &disk_setup,
308                                                      OG_PARAMS_RESP_REFRESH);
309                } else if (!strcmp(key, "partition_setup")) {
310                        err = og_json_parse_partition_array(value, partitions);
311                } else if (!strcmp(key, "serial_number")) {
312                        err = og_json_parse_string(value, &serial_number);
313                } else {
314                        return -1;
315                }
316
317                if (err < 0)
318                        return err;
319        }
320
321        if (strlen(serial_number) > 0)
322                snprintf(cfg, sizeof(cfg), "ser=%s\n", serial_number);
323
324        if (!disk_setup.disk || !disk_setup.number || !disk_setup.code ||
325            !disk_setup.filesystem || !disk_setup.os || !disk_setup.size ||
326            !disk_setup.used_size)
327                return -1;
328
329        snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
330                 "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
331                 disk_setup.disk, disk_setup.number, disk_setup.code,
332                 disk_setup.filesystem, disk_setup.os, disk_setup.size,
333                 disk_setup.used_size);
334
335        for (i = 0; i < OG_PARTITION_MAX; i++) {
336                if (!partitions[i].disk || !partitions[i].number ||
337                    !partitions[i].code || !partitions[i].filesystem ||
338                    !partitions[i].os || !partitions[i].size ||
339                    !partitions[i].used_size)
340                        continue;
341
342                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
343                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
344                         partitions[i].disk, partitions[i].number,
345                         partitions[i].code, partitions[i].filesystem,
346                         partitions[i].os, partitions[i].size,
347                         partitions[i].used_size);
348        }
349
350        dbi = og_dbi_open(&dbi_config);
351        if (!dbi) {
352                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
353                                  __func__, __LINE__);
354                og_dbi_free_computer_info(&computer);
355                return -1;
356        }
357
358        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
359        if (err < 0) {
360                og_dbi_close(dbi);
361                return -1;
362        }
363
364        res = actualizaConfiguracion(dbi, cfg, computer.id);
365        og_dbi_close(dbi);
366
367        if (!res) {
368                syslog(LOG_ERR, "Problem updating client configuration\n");
369                og_dbi_free_computer_info(&computer);
370                return -1;
371        }
372
373        if (!cli->autorun && computer.procedure_id) {
374                cli->autorun = true;
375
376                if (og_dbi_queue_autorun(computer.id, computer.procedure_id)) {
377                        og_dbi_free_computer_info(&computer);
378                        return -1;
379                }
380        }
381        og_dbi_free_computer_info(&computer);
382
383        return 0;
384}
385
386static int update_image_info(struct og_dbi *dbi, const char *image_id,
387                             const char *clonator, const char *compressor,
388                             const char *filesystem, const uint64_t datasize)
389{
390        const char *msglog;
391        dbi_result result;
392
393        result = dbi_conn_queryf(dbi->conn,
394                "UPDATE imagenes"
395                "   SET clonator='%s', compressor='%s',"
396                "       filesystem='%s', datasize=%lld"
397                " WHERE idimagen=%s", clonator, compressor, filesystem,
398                datasize, image_id);
399
400        if (!result) {
401                dbi_conn_error(dbi->conn, &msglog);
402                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
403                       __func__, __LINE__, msglog);
404                return -1;
405        }
406        dbi_result_free(result);
407
408        return 0;
409}
410
411static int og_resp_image_create(json_t *data, struct og_client *cli)
412{
413        struct og_software_legacy soft_legacy;
414        struct og_image_legacy img_legacy;
415        struct og_computer computer = {};
416        const char *compressor = NULL;
417        const char *filesystem = NULL;
418        const char *partition = NULL;
419        const char *software = NULL;
420        const char *image_id = NULL;
421        const char *clonator = NULL;
422        const char *disk = NULL;
423        const char *code = NULL;
424        const char *name = NULL;
425        const char *repo = NULL;
426        uint64_t datasize = 0;
427        struct og_dbi *dbi;
428        const char *key;
429        json_t *value;
430        int err = 0;
431        bool res;
432
433        if (json_typeof(data) != JSON_OBJECT)
434                return -1;
435
436        json_object_foreach(data, key, value) {
437                if (!strcmp(key, "software"))
438                        err = og_json_parse_string(value, &software);
439                else if (!strcmp(key, "partition"))
440                        err = og_json_parse_string(value, &partition);
441                else if (!strcmp(key, "disk"))
442                        err = og_json_parse_string(value, &disk);
443                else if (!strcmp(key, "code"))
444                        err = og_json_parse_string(value, &code);
445                else if (!strcmp(key, "id"))
446                        err = og_json_parse_string(value, &image_id);
447                else if (!strcmp(key, "name"))
448                        err = og_json_parse_string(value, &name);
449                else if (!strcmp(key, "repository"))
450                        err = og_json_parse_string(value, &repo);
451                else if (!strcmp(key, "clonator"))
452                        err = og_json_parse_string(value, &clonator);
453                else if (!strcmp(key, "compressor"))
454                        err = og_json_parse_string(value, &compressor);
455                else if (!strcmp(key, "filesystem"))
456                        err = og_json_parse_string(value, &filesystem);
457                else if (!strcmp(key, "datasize"))
458                        err = og_json_parse_uint64(value, &datasize);
459                else
460                        return -1;
461
462                if (err < 0)
463                        return err;
464        }
465
466        if (!software || !partition || !disk || !code || !image_id || !name ||
467            !repo || !clonator || !compressor || !filesystem || !datasize) {
468                syslog(LOG_ERR, "malformed response json\n");
469                return -1;
470        }
471
472        dbi = og_dbi_open(&dbi_config);
473        if (!dbi) {
474                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
475                       __func__, __LINE__);
476                return -1;
477        }
478
479        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
480        if (err < 0) {
481                og_dbi_close(dbi);
482                return -1;
483        }
484
485        snprintf(soft_legacy.center, sizeof(soft_legacy.center), "%d",
486                 computer.center);
487        snprintf(soft_legacy.software, sizeof(soft_legacy.software), "%s",
488                 software);
489        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
490                 image_id);
491        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
492        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
493        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
494        snprintf(img_legacy.code, sizeof(img_legacy.code), "%s", code);
495        snprintf(img_legacy.name, sizeof(img_legacy.name), "%s", name);
496        snprintf(img_legacy.repo, sizeof(img_legacy.repo), "%s", repo);
497
498        res = actualizaSoftware(dbi,
499                                soft_legacy.software,
500                                img_legacy.part,
501                                soft_legacy.id,
502                                computer.name,
503                                soft_legacy.center);
504        if (!res) {
505                og_dbi_free_computer_info(&computer);
506                og_dbi_close(dbi);
507                syslog(LOG_ERR, "Problem updating client configuration\n");
508                return -1;
509        }
510        og_dbi_free_computer_info(&computer);
511
512        res = actualizaCreacionImagen(dbi,
513                                      img_legacy.image_id,
514                                      img_legacy.disk,
515                                      img_legacy.part,
516                                      img_legacy.code,
517                                      img_legacy.repo,
518                                      soft_legacy.id);
519        if (!res) {
520                og_dbi_close(dbi);
521                syslog(LOG_ERR, "Problem updating client configuration\n");
522                return -1;
523        }
524
525        res = update_image_info(dbi, image_id, clonator, compressor,
526                                filesystem, datasize);
527        og_dbi_close(dbi);
528
529        if (res) {
530                syslog(LOG_ERR, "Problem updating image info\n");
531                return -1;
532        }
533
534        return 0;
535}
536
537static int og_resp_image_restore(json_t *data, struct og_client *cli)
538{
539        struct og_software_legacy soft_legacy;
540        struct og_image_legacy img_legacy;
541        struct og_computer computer = {};
542        const char *partition = NULL;
543        const char *image_id = NULL;
544        const char *disk = NULL;
545        dbi_result query_result;
546        struct og_dbi *dbi;
547        const char *key;
548        json_t *value;
549        int err = 0;
550        bool res;
551
552        if (json_typeof(data) != JSON_OBJECT)
553                return -1;
554
555        json_object_foreach(data, key, value) {
556                if (!strcmp(key, "partition"))
557                        err = og_json_parse_string(value, &partition);
558                else if (!strcmp(key, "disk"))
559                        err = og_json_parse_string(value, &disk);
560                else if (!strcmp(key, "image_id"))
561                        err = og_json_parse_string(value, &image_id);
562                else
563                        return -1;
564
565                if (err < 0)
566                        return err;
567        }
568
569        if (!partition || !disk || !image_id) {
570                syslog(LOG_ERR, "malformed response json\n");
571                return -1;
572        }
573
574        dbi = og_dbi_open(&dbi_config);
575        if (!dbi) {
576                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
577                       __func__, __LINE__);
578                return -1;
579        }
580
581        query_result = dbi_conn_queryf(dbi->conn,
582                                       "SELECT idperfilsoft FROM imagenes "
583                                       " WHERE idimagen='%s'",
584                                       image_id);
585        if (!query_result) {
586                og_dbi_close(dbi);
587                syslog(LOG_ERR, "failed to query database\n");
588                return -1;
589        }
590        if (!dbi_result_next_row(query_result)) {
591                dbi_result_free(query_result);
592                og_dbi_close(dbi);
593                syslog(LOG_ERR, "software profile does not exist in database\n");
594                return -1;
595        }
596        snprintf(img_legacy.software_id, sizeof(img_legacy.software_id),
597                 "%d", dbi_result_get_uint(query_result, "idperfilsoft"));
598        dbi_result_free(query_result);
599
600        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
601        if (err < 0) {
602                og_dbi_close(dbi);
603                return -1;
604        }
605
606        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
607                 image_id);
608        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
609        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
610        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
611
612        og_dbi_free_computer_info(&computer);
613
614        res = actualizaRestauracionImagen(dbi,
615                                          img_legacy.image_id,
616                                          img_legacy.disk,
617                                          img_legacy.part,
618                                          soft_legacy.id,
619                                          img_legacy.software_id);
620        og_dbi_close(dbi);
621
622        if (!res) {
623                syslog(LOG_ERR, "Problem updating client configuration\n");
624                return -1;
625        }
626
627        return 0;
628}
629
630int og_agent_state_process_response(struct og_client *cli)
631{
632        json_error_t json_err;
633        json_t *root;
634        int err = -1;
635        char *body;
636
637        if (!strncmp(cli->buf, "HTTP/1.0 202 Accepted",
638                     strlen("HTTP/1.0 202 Accepted"))) {
639                og_dbi_update_action(cli->last_cmd_id, true);
640                cli->last_cmd_id = 0;
641                return 1;
642        }
643
644        if (strncmp(cli->buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) {
645                og_dbi_update_action(cli->last_cmd_id, false);
646                cli->last_cmd_id = 0;
647                return -1;
648        }
649        og_dbi_update_action(cli->last_cmd_id, true);
650        cli->last_cmd_id = 0;
651
652        if (!cli->content_length) {
653                cli->last_cmd = OG_CMD_UNSPEC;
654                return 0;
655        }
656
657        body = strstr(cli->buf, "\r\n\r\n") + 4;
658
659        root = json_loads(body, 0, &json_err);
660        if (!root) {
661                syslog(LOG_ERR, "%s:%d: malformed json line %d: %s\n",
662                       __FILE__, __LINE__, json_err.line, json_err.text);
663                return -1;
664        }
665
666        switch (cli->last_cmd) {
667        case OG_CMD_PROBE:
668                err = og_resp_probe(cli, root);
669                break;
670        case OG_CMD_SHELL_RUN:
671                err = og_resp_shell_run(cli, root);
672                break;
673        case OG_CMD_HARDWARE:
674                err = og_resp_hardware(root, cli);
675                break;
676        case OG_CMD_SOFTWARE:
677                err = og_resp_software(root, cli);
678                break;
679        case OG_CMD_REFRESH:
680                err = og_resp_refresh(root, cli);
681                break;
682        case OG_CMD_SETUP:
683                err = og_resp_refresh(root, cli);
684                break;
685        case OG_CMD_IMAGE_CREATE:
686                err = og_resp_image_create(root, cli);
687                break;
688        case OG_CMD_IMAGE_RESTORE:
689                err = og_resp_image_restore(root, cli);
690                break;
691        default:
692                err = -1;
693                break;
694        }
695
696        cli->last_cmd = OG_CMD_UNSPEC;
697
698        return err;
699}
Note: See TracBrowser for help on using the repository browser.