source: ogServer-Git/src/client.c @ a8eccba

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

#971 rename sources folder to src

Use the same folder as in ogClient.

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